如何在Bash中处理每隔一行的文本

17
我想打印奇数行(1,3,5,7..),不做任何更改,但是对于偶数行(2,4,6,8),我想使用以grep开头的管道进行处理。我想将所有内容都写入新文件中(奇数行不做任何更改,偶数行有新值)。
我知道如何在awk中打印每隔一行:
awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print; }' file.fasta

然而,对于偶数行,我不想使用{print; },而是想使用我的grep管道。

感谢您的建议。


4
“==1{print;}”是多余的,简单地使用“awk 'NR%2'”将打印奇数行。 - Kevin
3个回答

16

如果你打算进行简单的grep,你可以省略额外的步骤,在awk内部进行过滤,例如:

awk 'NR % 2 {print} !(NR % 2) && /pattern/ {print}' file.fasta

然而,如果你打算做更多的事情,那么如chepner已经指出的,你确实可以从awk内部进行管道操作。例如:

awk 'NR % 2 {print} !(NR % 2) {print | "grep pattern | rev" }' file.fasta

这会打开一个到命令"grep pattern | rev"的管道(注意引号),并将打印输出重定向到它。请注意,在这种情况下,输出可能不如您预期;你最终会得到所有奇数行的输出,然后是被管道命令消耗的偶数行的输出。


(回应您的评论)要计算每个偶数行中字符的数量,请尝试:

awk 'NR % 2 {print} !(NR % 2) {print length($0)}' file.fasta

谢谢。我即将计算偶数行中字母的数量。 - Perlnika
@Perlnika,你可以使用awk中的length命令来获取字符数。请查看更新后的答案。 - Shawn Chin
@Perlnika,一些fasta文件可能包含像“-”或“X”这样的奇怪字符,但您可能已经回答了OP想要的内容。 - Steve
@ShawnChin 非常感谢,我使用了$0而不是0,现在它可以工作了! - Perlnika
抱歉,之前打错了。应该是 length($0)。回答已更新。 - Shawn Chin
啊哈,你比我先发现了它 ;) 很高兴它有帮助。 - Shawn Chin

8
你可以直接在awk内部使用管道:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print | "grep -o [actgnACTGN] | wc -l"; }' file.fasta

请注意,这样做不会保留您输入文件的顺序。

(选定的答案更适合当前任务,但我将保留此答案作为将打印语句传输到外部命令的示例。)


谢谢,我已经尝试使用awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print | grep -o [actgnACTGN] | wc -l }' file.fasta(为了计算行中字母的数量),但是wc出现问题,显示:awk: line 1: syntax error at or near wc(所以我猜测问题在我的管道中 :))。 - Perlnika
不保留顺序是什么意思? - Perlnika
@Perlnika 他的意思是你最终会先输出所有奇数行,然后紧接着是管道的输出(消耗了所有偶数行)。 - Shawn Chin
在我运行的简短测试中,所有奇数行都被打印出来,接着是由grep输出的偶数行。这是因为 grep 的输出可能需要与 awk 的输出合并,而 awk 的输出可能是不确定的。此外,这种方法可能是低效的,因为我认为每个偶数行都会 fork 一个单独的 grep - chepner
抱歉,引用中出现了一个错误,我以为已经修复了。请查看我的更新。 - chepner

2
为了使您的管道输出与AWK输出按顺序出现,您需要在每次迭代时关闭管道。当然,这样非常低效。
awk 'BEGIN{ cmd = "grep -io \047[actgn]\047 | wc -l" } NR % 2 { print } NR % 2 == 0 { print | cmd; close(cmd) }' file.fasta

显然,您不希望计算不在指定列表中的字符,因此length($0)无法使用。以下方法可以解决问题,并且应该比流水线方法快得多:

awk 'NR % 2 { print } NR % 2 == 0 {n = split($0, a, /[^actgnACTGN]/); print length($0) - n + 1}' file.fasta

它的工作原理是使用您不想要的字符作为分隔符来拆分行,并从行的长度中减去子字符串的计数并加上1。本质上,它从行的长度中减去不需要的字符数,将所需字符的数量留作结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接