bash:意外标记“|”附近的语法错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32583542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
bash: syntax error near unexpected token `|'
提问by Sourabh
This command works well in command prompt :
此命令在命令提示符下运行良好:
]$ ls -ltr ../cmxserver.log*|grep "`date | awk '{print " "}'`"|cut -d "/" -f2
cmxserver.log.2
cmxserver.log.1
cmxserver.log
However, using this in for loop gives error bash: syntax error near unexpected token `|'
但是,在 for 循环中使用它会给出错误 bash: syntax error near unexpected token `|'
]$for y in `ls -ltr ../cmxserver.log*|grep "`date | awk '{print " "}'`"|cut -d "/" -f2`
-bash: syntax error near unexpected token `|'
Any idea ?
任何的想法 ?
Thanks
谢谢
回答by mitroo
The whole line can be solved by find
command:
整行可以通过find
命令解决:
find .. -maxdepth 1 -mtime -1 -daystart -name 'cmxserver.log*' -printf "%f\n"
..
- directory where to search-maxdepth 1
- don't go recursive to subdirectories-mtime -1
- only today's files-daystart
- count the day since midnight, not last 24 hrs-name 'cmxserver.log*'
- filenames-printf "%f\n"
- print only basename
..
- 搜索目录-maxdepth 1
- 不要递归到子目录-mtime -1
- 只有今天的文件-daystart
- 从午夜开始算一天,而不是过去 24 小时-name 'cmxserver.log*'
- 文件名-printf "%f\n"
- 仅打印基本名称
回答by rici
You probably understood what you meant when you typed:
当您键入时,您可能理解了您的意思:
for y in `ls -ltr ../cmxserver.log*|grep "`date | awk '{print " "}'`"|cut -d "/" -f2`
But you have managed to completely confuse bash. Bash (and other shells) don't nest backticks (`) unless the inner ones are backslashed. As written, the second backtick is considered to close the first one, resulting in the command ls -ltr ../cmxserver.log*|grep "
. Since you did not put a space before date
, the word date
is parsed as part of the word including the command substitution. Similarly, the single-quoted '{print $2"$3}'
is parsed as being prepended to the backticked command "|cut -d "/" -f2
.
但是您已经成功地完全混淆了 bash。Bash(和其他 shell)不会嵌套反引号 ( `),除非内部反斜杠被反斜杠。正如所写,第二个反引号被认为是关闭第一个反引号,从而产生命令ls -ltr ../cmxserver.log*|grep "
. 由于您没有在 之前放置空格date
,因此该词将date
被解析为该词的一部分,包括命令替换。类似地,单引号'{print $2"$3}'
被解析为前置到反引号 command "|cut -d "/" -f2
。
Of course, both of those backticked commands are syntax errors because they contain unclosed double quotes, but before bash reaches the point of parsing and executing the commands, it is left with something which roughly speaking looks like:
当然,这两个反引号命令都是语法错误,因为它们包含未关闭的双引号,但是在 bash 到达解析和执行命令的点之前,它留下了一些粗略地说看起来像的东西:
for y in word1 | awk word2
which is a syntax error because the pipe symbol can only appear between complete commands, and for y in word1
is not a complete command.
这是一个语法错误,因为管道符号只能出现在完整命令之间,而for y in word1
不是完整命令。
Backticks are deprecated. Stop using them.
不推荐使用反引号。停止使用它们。
If you had written:
如果你写过:
for y in $(ls -ltr ../cmxserver.log* |
grep "$(date | awk '{print " "}')" |
cut -d "/" -f2)
both bash and human readers would have found the expression much easier to parse, and bash would have parsed it as you expected.
bash 和人类读者都会发现该表达式更容易解析,而且 bash 会按照您的预期解析它。
Having said that, it is never a good ideato try to parse ls
output, and it is never necessary to parse date
output because you can specify a formatstring; in this case, you could have used date +"%b %d"
to get the month and day. (First link courtesy of a comment by Charles Duffy.)
话虽如此,尝试解析输出从来都不是一个好主意ls
,也从来没有必要解析date
输出,因为你可以指定一个格式字符串;在这种情况下,您可以使用date +"%b %d"
获取月份和日期。(第一个链接来自 Charles Duffy 的评论。)