为什么在这种情况下会丢失双引号?
$ cat foo.txt
This is a \"very good\" text worth AMOUNT dollars
$ cat full_story.txt
This is about money:
STORY
使用以下命令进行测试:
VAR=$(cat foo.txt)
TOTAL=$(cat full_story.txt)
echo "$TOTAL" | perl -pe "s/STORY/$VAR/g"
结果:
This is about money:
This is a "very good" text worth AMOUNT dollars
双引号的转义丢失了。我期待:
This is about money:
This is a \"very good\" text worth AMOUNT dollars
我如何保存逃生通道?
答案 0 :(得分:4)
问题在于perl
在一个显式替换字符串(不是perl
变量中解析反斜杠转义),因此将\"
解析为"
。例如:
$ echo "A STORY" | perl -pe 's/STORY/\"Hello\"/'
A "Hello"
(请注意,Bash变量$VAR
不会变成perl
变量$VAR
,而是一个常量字符串。)因此,您需要在常量字符串中转义这样的反斜杠:
$ echo "A STORY" | perl -pe 's/STORY/\\"Hello\\"/'
A \"Hello\"
您可以通过将-s
切换到$VAR
,将Bash变量perl
转换为$VAR
变量perl
来解决此问题:
echo "$TOTAL" | perl -spe 's/STORY/$VAR/g' -- -VAR="$VAR"
输出:
This is about money:
This is a \"very good\" text worth AMOUNT dollars
说明:
perl
命令行上的用户定义开关启用开关解析。在@ARGV
中删除在那里找到的所有开关,并在Perl程序中设置相应的变量。答案 1 :(得分:3)
您的代码遭受code injection错误。具体来说,您正在尝试从shell生成Perl代码,但失败了。
您将以下内容传递给Perl:
s/STORY/This is a \"very good\" text worth AMOUNT dollars/g
您应该通过以下内容:
s/STORY/This is a \\"very good\\" text worth AMOUNT dollars/g
要正确生成Perl代码,您需要以下内容:
perl -pe's/STORY/'"$( printf %s "$VAR" | sed 's/\W/\\&/g' )"'/'
这会将以下内容传递给Perl(也可以):
s/STORY/This is a \\\"very good\\\" text worth AMOUNT dollars/g
但是,首先避免生成Perl代码要容易得多。不使用STDIN或外部存储将信息传递给Perl的主要方法有三种。
参数
perl -pe'BEGIN { $VAR = shift(@ARGV) } s/STORY/$VAR/g' -- "$VAR"
命令行选项
在完整程序中,您将使用Getopt::Long,但是perl -s
在这里可以正常工作。
perl -spe's/STORY/$VAR/g' -- -VAR="$VAR"
环境变量
VAR="$VAR" perl -pe's/STORY/$ENV{VAR}/g'