如何使用`sed`来改变bash脚本中的变量?

Ama*_*nda 0 bash sed

我正在尝试使用enscript从Mutt打印PDF,并遇到字符编码问题.围绕它们的一种方法似乎只是sed用来替换问题字符:sed -ir 's/[“”]/"/g' {input}

我的测试输入文件是这样的:

“very dirty”    
we’re 
Run Code Online (Sandbox Code Playgroud)

我希望得到"very dirty",we're但我仍然得到

â\200\234very dirtyâ\200\235
weâ\200\231re
Run Code Online (Sandbox Code Playgroud)

我发现了一个很好的关于从Mutt打印到PDF的小帖子,我用它作为起点.我有一个bash脚本,我点从我.muttrcset print_command="$HOME/.mutt/print.sh"-剧本目前像这样读取有关:

#!/bin/bash
input="$1" pdir="$HOME/Desktop" open_pdf=evince


# Straighten out curly quotes

sed -ir 's/[“”]/"/g' $input
sed -ir "s/[’]/'/g" $input


tmpfile="`mktemp $pdir/mutt_XXXXXXXX.pdf`"
enscript --font=Courier8 $input -2r --word-wrap --fancy-header=mutt -p - 2>/dev/null | ps2pdf - $tmpfile
$open_pdf $tmpfile >/dev/null 2>&1 &
sleep 1
rm $tmpfile
Run Code Online (Sandbox Code Playgroud)

它在创建PDF方面做得很好(如果你把它作为参数给它一个文件也可以正常工作),但我无法弄清楚如何修复卷曲引号.

我尝试了一系列的变化sed:

input=sed -r 's/[“”]/"/g' $input

$input=sed -ir "s/[’]/'/g" $input
Run Code Online (Sandbox Code Playgroud)

根据的建议我可以使用sed来操纵bash中的变量吗?我也试过 input=$(sed -r 's/[“”]/"/g' <<< $input),我得到一个错误:"语法错误:重定向意外"

但没有管理真正改变$input-什么是正确的语法更改$inputsed

注意:我接受了一个解决了我问的问题的答案,但正如您从评论中看到的那样,这里还有其他一些问题.enscript将整个文件作为变量,而不仅仅是文件的文本.因此,尝试调整文件中的文本将需要一些额外的步骤.我还在学习.

Cha*_*ffy 5

关于一般编辑变量的研究

BashFAQ#21是关于在bash中执行搜索和替换操作的综合参考,包括在变量中,因此建议阅读.在这个特殊情况下:

改为使用shell的本机字符串操作; 这比离开子shell,在其中启动外部进程以及读取外部进程的输出要高得多.BashFAQ#100详细介绍了这个主题,非常值得一读.

根据您的bash和配置的语言环境的版本,可能使用括号表达式(即[“”],如原始代码所做的那样).然而,最便携的事情是治疗分开,这将工作,即使没有可用的多字节字符支持.

input='“hello ’cruel’ world”'
input=${input//'“'/'"'}
input=${input//'”'/'"'}
input=${input//'’'/"'"}
printf '%s\n' "$input"
Run Code Online (Sandbox Code Playgroud)

......正确输出:

"hello 'cruel' world"
Run Code Online (Sandbox Code Playgroud)

关于使用 sed

提供一个字面的答案 - 你几乎sed在你的问题中有一个基于工作的方法.

input=$(sed -r 's/[“”]/"/g' <<<"$input")
Run Code Online (Sandbox Code Playgroud)

...在参数扩展周围添加缺少的语法双引号$input,确保将其视为单个标记,而不管它是如何进行字符串拆分或全局扩展.


但那可能无济于事......

提到以下内容是因为您的测试脚本正在操作在命令行上传递的内容; 如果在生产中不是这种情况,你可以忽略以下内容.

如果您的脚本被调用为./yourscript “hello * ’cruel’ * world”,那么在脚本启动之前,有关用户输入的确切内容的信息将丢失,您在此处无需执行任何操作即可解决此问题.

这是因为$1,在那种情况下,只会包含“hello; ’cruel’并且world”它们位于自己的argv位置,并且*在脚本启动之前,s将被替换为当前目录中的文件列表(每个此类文件替换为单独的参数).因为负责解析用户命令行的shell(运行脚本的shell不一样!)在运行此解析时没有将引号识别为有效,所以在脚本运行时,没有什么可以做的做恢复原始数据.