我有很多正在运行的后台作业正在提供各自的日志文件。使用watch
命令我正在监视日志中的相应最后一行,如下所示。
watch "ls -rtdc1 base_*.log | tail -20 | xargs -I % sh -c 'tail -vn1 % | cut -c1-180'"
看起来很不错,但它的文件名来自tail -v
,并且日志后面有一行换行符。我想两者保持一致。下面的小awk cmd将只组合两行,它可以单独测试。
awk 'NR%2{printf "%s ",$0;next;}1'
好的,现在结合这两个是挑战。很多单引号和双引号值得注意。我尝试了以下一行失败了。
watch "ls -rtdc1 base_*.log | tail -20 | xargs -I % sh -c 'tail -vn1 % | awk \'NR%2{printf "%s ",$0;next;}1\' | cut -c1-180'"
所以我的问题是为cmd线找到正确的转义序列。
非常感谢您的反馈。
答案 0 :(得分:1)
正确的做法是以这样一种方式构建代码,使您根本不需要引用代码来使其按字面意思处理。
请考虑以下内容(注意到我的函数定义在此处占位符的任何地方,它应该替换为给定的myfn
定义,或者等效于其中的东西):
#!/usr/bin/env bash
# ^^^^-- needed for exported functions
myfn() {
# aside: parsing ls is a Really Bad Idea; don't do this.
# See https://mywiki.wooledge.org/ParsingLs for discussion of why not.
# See https://mywiki.wooledge.org/BashFAQ/003 for alternate practices.
ls -rtdc1 base_*.log \
| tail -20 \
| while read -r line; do
tail -v1 "$line" \
| awk 'NR%2 {printf "%s ",$0; next; }1' \
| cut -c1-180
done
}
export -f myfn
watch 'bash -c myfn'
或者,没有export -f
(并且要求bash仅作为外壳,而不是内壳):
#!/usr/bin/env bash
# ^^^^- needed for declare -f
myfn() { echo "Function definition goes here"; }
watch "$(declare -f myfn); myfn"
或者,只需要 / bin / sh:
#!/bin/sh
cat_myfn() {
cat <<'EOF'
myfn() { echo "Function definition goes here"; }
EOF
}
watch "$(cat_myfn)
myfn"
答案 1 :(得分:1)
查尔斯对你的具体问题有一个很好的答案。如果你问的是引用的一般问题,那么GNU Parallel可以为你做到这一点:
$ parallel --shellquote
NR%2{printf "%s ",$0;next;}1
[Ctrl-D]
所以awk NR%2\{printf\ \"%s\ \",\$0\;next\;\}1
应该有用。接下来引用sh -c
的命令:
$ parallel --shellquote
tail -vn1 % | awk NR%2\{printf\ \"%s\ \",\$0\;next\;\}1 | cut -c1-180
[Ctrl-D]
,并提供:
tail\ -vn1\ %\ \|\ awk\ NR%2\\\{printf\\\ \\\"%s\\\ \\\",\\\$0\\\;next\\\;\\\}1\ \|\ cut\ -c1-180
但是,由于您在awk
命令中使用%,因此需要为xargs
使用另一个替换字符串。我们使用{}:
ls -rtdc1 base_*.log | tail -20 | xargs -I {} sh -c tail\ -vn1\ {}\ \|\ awk\ NR%2\\\{printf\\\ \\\"%s\\\ \\\",\\\$0\\\;next\\\;\\\}1\ \|\ cut\ -c1-180
最后引用watch
:
$ parallel --shellquote
ls -rtdc1 base_*.log | tail -20 | xargs -I {} sh -c tail\ -vn1\ {}\ \|\ awk\ NR%2\\\{printf\\\ \\\"%s\\\ \\\",\\\$0\\\;next\\\;\\\}1\ \|\ cut\ -c1-180
[Ctrl-D]
,并提供:
ls\ -rtdc1\ base_\*.log\ \|\ tail\ -20\ \|\ xargs\ -I\ \{\}\ sh\ -c\ tail\\\ -vn1\\\ \{\}\\\ \\\|\\\ awk\\\ NR%2\\\\\\\{printf\\\\\\\ \\\\\\\"%s\\\\\\\ \\\\\\\",\\\\\\\$0\\\\\\\;next\\\\\\\;\\\\\\\}1\\\ \\\|\\\ cut\\\ -c1-180
因此应该有效:
watch ls\ -rtdc1\ base_\*.log\ \|\ tail\ -20\ \|\ xargs\ -I\ \{\}\ sh\ -c\ tail\\\ -vn1\\\ \{\}\\\ \\\|\\\ awk\\\ NR%2\\\\\\\{printf\\\\\\\ \\\\\\\"%s\\\\\\\ \\\\\\\",\\\\\\\$0\\\\\\\;next\\\\\\\;\\\\\\\}1\\\ \\\|\\\ cut\\\ -c1-180
你会用手写这种方式吗?可能不是。但是整个想法是让计算机为你工作 - 而不是相反。