首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >文件中带有引号的grep字符串不起作用

文件中带有引号的grep字符串不起作用
EN

Stack Overflow用户
提问于 2016-08-16 04:05:04
回答 2查看 463关注 0票数 1

我有一个文件,其中包含:

代码语言:javascript
复制
2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A \"restart\" -CS \"Undefined\" -RS \"Undefined\" -CT \"Undefined\" -RT \"Undefined\" --LogServer logserver:5610

当我试图跟踪一个执行日志时,我正在检查日志文件是否包含最新的日志。看看这个字符串是否存在。我尝试过grep -F,grep -E,grep -FFxq,所以简而言之就是:

代码语言:javascript
复制
CurrentLog="2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A \"restart\" -CS \"Undefined\" -RS \"Undefined\" -CT \"Undefined\" -RT \"Undefined\" --LogServer logserver:5610"

请注意,CurrentLog的填充方式如下:

代码语言:javascript
复制
CurrentLog=$(echo "$OutputTail" | jq ".entries[$EntryCoun‌​t].log" | sed -e 's/^"//' -e 's/"$//' ) 

意思是我不能只用单引号。

代码语言:javascript
复制
grep -Fxq "$CurrentLog" "/usr/local/nagios/libexec/DAF-988e7506-36c3-47e3-8ef2-428309e2c7f7-670.log"

似乎我需要同时转义“”和"\“。我如何在一个命令中做到这一点?我希望-F不会要求我添加额外的转义。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-08-16 04:19:20

为了避免转义双引号和反斜杠,您可以在变量声明两边使用单引号:

代码语言:javascript
复制
CurrentLog='2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A \"restart\" -CS \"Undefined\" -RS \"Undefined\" -CT \"Undefined\" -RT \"Undefined\" --LogServer logserver:5610'

测试变量内容:

代码语言:javascript
复制
declare -p CurrentLog
declare -- CurrentLog="2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A \\\"restart\\\" -CS \\\"Undefined\\\" -RS \\\"Undefined\\\" -CT \\\"Undefined\\\" -RT \\\"Undefined\\\" --LogServer logserver:5610"

然后使用它作为:

代码语言:javascript
复制
grep -qFx "$CurrentLog" file && echo "matched" || echo "nope"

matched

另一种方法是使用here-doc声明您的变量,而不用担心引用:

代码语言:javascript
复制
read -r CurrentLog <<-'EOF'
2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A \"restart\" -CS \"Undefined\" -RS \"Undefined\" -CT \"Undefined\" -RT \"Undefined\" --LogServer logserver:5610
EOF

或者最好避免创建单独的变量,而使用进程替换:

代码语言:javascript
复制
read -r CurrentLog < <(jq -r --arg EntryCount "$EntryCount" '.entries[$EntryCoun‌​‌​‌​‌​t | tonumber].log' <<< "$OutputTail")
票数 1
EN

Stack Overflow用户

发布于 2016-08-16 04:12:52

反斜杠需要加倍;嵌入的双引号也需要转义(反斜杠)。因此,您最终会在CurrentLog中出现\\\"

代码语言:javascript
复制
CurrentLog="2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A \\\"restart\\\" -CS \\\"Undefined\\\" -RS \\\"Undefined\\\" -CT \\\"Undefined\\\" -RT \\\"Undefined\\\" --LogServer logserver:5610"

此外,正如Charles Duffy在他的comment中提醒我的那样,最好在赋值两边使用单引号,因为您不需要展开任何变量或进行命令替换:

代码语言:javascript
复制
CurrentLog='2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A \"restart\" -CS \"Undefined\" -RS \"Undefined\" -CT \"Undefined\" -RT \"Undefined\" --LogServer logserver:5610'

显然,如果你简化了问题的字符串(例如,server实际上是从一个变量扩展而来的),那么你需要重新考虑这一点。也要认真考虑.*的建设性使用,以匹配引用的内容。您不太可能拥有多个所有内容都相同的日志,除了一个日志在字符串中的同一点上有"restart",另一个日志中有"Undefined"。使用正则表达式是平衡相关内容和不相关内容的一门艺术。

但总有一天(在达到这种状态之前的某个地方),最好是将要匹配的字符串放入文件中,并使用与grep匹配的文件和固定字符串

代码语言:javascript
复制
grep -F -f file-containing-pattern-line file-to-be-searched …

这样,您就不必对抗shell的引用和转义机制(或者,至少在创建file-containing-pattern-line时)。还有-x选项,用于“精确匹配整行”。

别忘了这里包含引号的文档是不会被解释的:

代码语言:javascript
复制
cat > file-containing-pattern-line << 'EOF'
2016-08-15 21:02:59,007: 233-670-rundeck-dispatch-script.tmp.sh: Info: Arg: -H server -S SrvCtrl,SNMP -A "restart" -CS "Undefined" -RS "Undefined" -CT "Undefined" -RT "Undefined" --LogServer logserver:5610
EOF

您还应该考虑是否真的需要匹配所有这些内容。仅仅日期/时间或者日期/时间加上脚本名称(233-670-rundeck-dispatch-script.tmp.sh)就足够了吗?其中一个可能就足够了,并且只需在其中匹配就可以极大地简化代码的阅读。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38962242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档