使用C Shell,以下命令行
set pf = "`awk -v var=$pd '{if($1<0) print var, $2, $3}' test.txt`"
返回awk错误:
awk: {if( <0) print var, , } syntax error.
这尤其令人困惑,因为命令本身可以正常工作:
awk -v var=$pd '{if($1<0) print var, $2, $3}' test.txt
有没有一种方法可以将单个Awk命令行的所有输出存储到单个变量中?以上失败的原因是什么?
答案 0 :(得分:0)
经过一番修补,我只能得出结论,它是那些C-Shell怪癖之一。 C壳(csh
或tcsh
)显然以其peculiarities闻名,我相信这正是这里发生的事情。以下是一些基于OP的示例的示例。
未引用:
$ set a = `echo a_b c | awk '{print $1}'` ; echo $a
a_b
$ set a = `echo a_b c | awk '{print $1,2}'` ; echo $a
a_b 2
$ set a = `echo a_b c | awk '{print $1 OFS 2}'` ; echo $a
a_b 2
引用:
$ set a = "`echo a_b c | awk '{print $1}'`" ; echo $a
a_b c
$ set a = "`echo a_b c | awk '{print $1,2}'`" ; echo $a
awk: cmd. line:1: {print ,2}
awk: cmd. line:1: ^ syntax error
$ set a = "`echo a_b c | awk '{print $1 OFS 2}'`" ; echo $a
2
因此,在带双引号的示例中,$1
看起来像是一个空字符串。这解释了为什么第一种情况打印全行a_b c
,而第三种情况仅打印数字2
。第二个失败,因为Awk语句print ,2
无效,而第一个以print
的形式等效于Awk中的print $0
。
如果您玩的更多,您实际上会注意到C-shell尝试进行变量替换。实际上,您实际上不需要在所有上述内容中使用set
,只需简单的双引号命令替换即可。下面的示例完全显示了香蕉的用途:
$ echo $0
csh
$ echo "`echo a_b c | awk '{print $0}'`"
$ echo "`echo a_b c | awk -v csh=foo '{print $0}'`"
foo
$ echo `echo a_b c | awk -v csh=foo '{print $0}'`
a_b c
因此,您会看到C-Shell正在执行变量替换,并且$0
被替换为字符串csh
。 但只能在双引号中!
那么,为什么会这样?原因是双引号。双引号字符串允许变量替换,而不必考虑双引号字符串中嵌套引号的用法。因此,即使Awk行在向后引用的字符串中被单引号引起来,双引号仍将在$n
上进行变量替换。这与Bash相反:
$ echo $0
bash
$ echo "`echo a_b c | awk -v csh=foo '{print $0}'`"
a_b c
词法结构
此外,可以通过用单引号将出现在其中的字符串(或字符串的一部分)用单引号引起来或引用关键字符来防止除历史替换以外的所有替换(请参见下文) (例如,分别使用
$
或`
进行变量替换或命令替换)。 (别名替换也不例外:以任何方式引用已定义别名的单词的任何字符都可以防止替换 别名。引用别名的常用方法是在其前面加上反斜杠。)历史记录替换通过反斜杠而不是单引号防止。 用双引号或反引号引起来的字符串会进行变量替换和命令替换,但是会禁止其他替换。引用复杂的字符串,尤其是本身包含引号的字符串可能会造成混淆。请记住,在人类写作中不必使用引号!并非只引用整个字符串,而是只引用需要引用的字符串部分,如果需要,可以使用不同类型的引用来引用。
来源:
\
那么,如何解决呢?尽管C-shell完全不直观并且在精神上是引用的噩梦,但可以通过提前终止引用并将其从double更改为double来解决问题。短时间内用单引号引起来。
man csh
解决方案:因此,在完成所有这些之后,我认为我们可以得出结论
$ echo "`echo a_b c | awk -v csh=foo '{print "'$0,$1'"}'`"
a_b c a_b
$ echo "`echo a_b c | awk -v csh=foo '"'{print $0,$1}'"'`"
a_b c a_b
可以潜在地解决问题。