我有很多后台作业在运行它们各自的日志文件。使用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线的正确转义序列。
非常感谢您的反馈。
正确的事情是以这样的方式构建代码,使得您根本不需要引用代码来使其按字面意思处理。
请考虑以下内容(注意到我在函数定义的任何地方都在下面的占位符中,它应该替换为给定的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"
查尔斯对你的具体问题有一个很好的答案。如果你问的是引用的一般问题,那么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
你会用手写这种方式吗?可能不是。但是整个想法是让计算机为你工作 - 而不是相反。