ceh*_*ptr 5 command-line sed gzip
我有一堆 gz 文件,它们的解压缩版本包含模式A和B=1(这些肯定位于A首先出现的不同行上)。
A我想编写一个命令,给出当前行和当前行的内容B=1。A或者至少是介于和之间的内容B=1。
输入文件1:
..A ...
...
...B=0..
...
Run Code Online (Sandbox Code Playgroud)
输入文件2:
..A ...
...
...B=1..
...
Run Code Online (Sandbox Code Playgroud)
我的命令必须A ....B=1为 file2输出,而为 file1不输出任何内容。
我做了类似的事情,但没有按预期工作:
find . -name \*.gz -print0 | xargs -0 zcat | sed -n -e '/A/,/B=1/p'
Run Code Online (Sandbox Code Playgroud)
这里有什么问题?
现在让我们忽略压缩。A您想要输出和之间的行B=1,但前提是两者都出现。您sed使用的不会这样做,因为它一看到就开始输出A,并且不检查B=1. 我们可以使用保持缓冲区来sed保留所有内容,直到B=1找到为止,但我对 更满意awk,所以这里:
$ echo -en 'not this\nA\nthis\nB=1\nnot this\n' |
awk '/A/ {save=1} save {data = data $0 ORS} /B=0/ {save=0; data=""} /B=1/ {save=0; printf "%s", data; data=""} '
A
this
B=1
Run Code Online (Sandbox Code Playgroud)
该B=0规则处理不应打印的块。
然后,处理压缩和多个文件。find您所做的 +有效xargs,但如果某些文件可以有部分块(A没有B),则将文件连接在一起会导致问题。假设情况并非如此,我们可以将 awk 放在最后:
$ find . -name foo\*.gz -print0 | xargs -0 zcat | \
awk '/A/ {s=1} s {d = d $0 ORS} /B=0/ {s=0; d=""}
/B=1/ {s=0; printf "%s", d; d=""} '
Run Code Online (Sandbox Code Playgroud)
如果我们确实需要处理部分块,则必须单独处理每个文件:
$ find . -name foo\*.gz -print0 | xargs -0 sh -c '
for f; do zcat "$f" | awk '\''/A/ {s=1} s {d = d $0 ORS}
/B=0/ {s=0; d=""} /B=1/ {s=0; printf "%s", d; d=""} '\''; done' sh
Run Code Online (Sandbox Code Playgroud)
引用很糟糕,所以awk脚本可能应该有自己的文件。
或者只是在 shell 中执行(Bash/ksh/zsh):
$ shopt -s globstar # set -o globstar in ksh
$ for f in **/*.gz ; do zcat "$f" |
awk '/A/ {s=1} s {d = d $0 ORS} /B=0/ {s=0; d=""}
/B=1/ {s=0; printf "%s", d; d=""} ' ; done
Run Code Online (Sandbox Code Playgroud)
如果您只想打印中间的行(而不是A和行),请交换和块B=1的位置。/A/ {...}/B=.../ {...}
| 归档时间: |
|
| 查看次数: |
26183 次 |
| 最近记录: |