为什么双引号awk命令替换在csh中失败

为什么双引号awk命令替换在csh中失败,awk,csh,tcsh,Awk,Csh,Tcsh,使用C shell,以下命令行 set pf = "`awk -v var=$pd '{if($1<0) print var, $2, $3}' test.txt`" set pf=“`awk-v var=$pd'{if($1)经过一些修补,我只能得出结论,这是C-Shell的怪癖之一。C-Shell(csh或tcsh)显然以其独特的功能而闻名,我相信这正是这里发生的事情。以下是一些基于OP之谜的例子 无引号: $ set a = `echo a_b c | awk '{print $1

使用C shell,以下命令行

set pf = "`awk -v var=$pd '{if($1<0) print var, $2, $3}' test.txt`"

set pf=“`awk-v var=$pd'{if($1)经过一些修补,我只能得出结论,这是C-Shell的怪癖之一。C-Shell(
csh
tcsh
)显然以其独特的功能而闻名,我相信这正是这里发生的事情。以下是一些基于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
引用:

$ 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
o
以Awk打印$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
词汇结构

此外,除了历史替换以外的所有替换(见下文)都可以通过用单引号括起它们出现的字符串(或字符串的一部分)或用
\
引用关键字符(例如,
$
`
分别表示变量替换或命令替换)来防止。(别名替换也不例外:以任何方式引用已定义别名的单词的任何字符都可以防止替换 别名。引用别名的通常方法是在其前面加反斜杠。)历史替换通过反斜杠而不是单引号来阻止。用双引号或反引号引用的字符串进行变量替换和命令替换,但防止其他替换。

引用复杂字符串,特别是本身包含引用字符的字符串,可能会造成混淆。请记住,引用不必像人类书写时那样使用!引用可能更容易,不必引用整个字符串,而只引用需要引用的字符串部分,如果合适,可以使用不同类型的引用

来源:
man csh

那么,如何解决这个问题呢?虽然C-shell完全没有直觉,在心理上是一个引用的噩梦,但可以通过提前终止引用并在短时间内从双引号改为单引号来解决这个问题

$ 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
解决方案:所以在所有这些之后,我想我们可以得出这样的结论

$ set pf = "`awk -v var=$pd '"'{if($1<0) print var, $2, $3}'"' test.txt`"

$set pf=“`awk-v var=$pd'”{if($1欢迎使用SO,因为我没有
csh
,所以无法测试它。对于初始故障排除,您能否只运行
awk
命令并查看您得到了什么错误?在命令行中一次性使用awk没有问题(awk-v var=$pd'{if($1请您尝试一下下面的内容,
set pf=$(awk-v var=$pd'{if($1不起作用。语法适合您的命令?我已经提到我没有
csh
,所以这只是猜测,请注意这在BASH上起作用了,请尝试让我知道。是的,在某些情况下你是对的。但是这个答案不是我想要的。我确实需要了解问题中给出的代码。如果它不能ork,请给代码一个明确的答案。谢谢。你的答案不是正确的答案。我使用双引号的原因是为了得到整个数据表(你可以尝试其他任务,比如双引号中的更多任务).我想知道awk任务是否可以在双引号中使用的确切答案。如果可以在双引号中使用,如何成功使用。如果不能,请给出一个明确的答案。感谢kavantour的演练。解决方案似乎有点奇怪。也许这就是Cshell的弱点。总之,它解决了问题。正如对于您的评论,我正在考虑使用Bshell intead:-)谢谢您一直以来的支持。