我有一个文件,其中包含:
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,所以简而言之就是:
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的填充方式如下:
CurrentLog=$(echo "$OutputTail" | jq ".entries[$EntryCount].log" | sed -e 's/^"//' -e 's/"$//' ) 意思是我不能只用单引号。
grep -Fxq "$CurrentLog" "/usr/local/nagios/libexec/DAF-988e7506-36c3-47e3-8ef2-428309e2c7f7-670.log"似乎我需要同时转义“”和"\“。我如何在一个命令中做到这一点?我希望-F不会要求我添加额外的转义。
发布于 2016-08-16 04:19:20
为了避免转义双引号和反斜杠,您可以在变量声明两边使用单引号:
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'测试变量内容:
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"然后使用它作为:
grep -qFx "$CurrentLog" file && echo "matched" || echo "nope"
matched另一种方法是使用here-doc声明您的变量,而不用担心引用:
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或者最好避免创建单独的变量,而使用进程替换:
read -r CurrentLog < <(jq -r --arg EntryCount "$EntryCount" '.entries[$EntryCount | tonumber].log' <<< "$OutputTail")发布于 2016-08-16 04:12:52
反斜杠需要加倍;嵌入的双引号也需要转义(反斜杠)。因此,您最终会在CurrentLog中出现\\\"。
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中提醒我的那样,最好在赋值两边使用单引号,因为您不需要展开任何变量或进行命令替换:
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匹配的文件和固定字符串
grep -F -f file-containing-pattern-line file-to-be-searched …这样,您就不必对抗shell的引用和转义机制(或者,至少在创建file-containing-pattern-line时)。还有-x选项,用于“精确匹配整行”。
别忘了这里包含引号的文档是不会被解释的:
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)就足够了吗?其中一个可能就足够了,并且只需在其中匹配就可以极大地简化代码的阅读。
https://stackoverflow.com/questions/38962242
复制相似问题