如何在bash中处理每一行

时间:2012-07-19 12:07:53

标签: bash awk

我想打印奇数行(1,3,5,7 ..)而没有任何改变,但偶数行(2,4,6,8)处理以grep开头的管道。我想把所有东西都写到新文件中(没有任何改变的奇数行和偶数行的新值)。

我知道如何在awk中打​​印所有其他行:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print; }' file.fasta

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

我们将不胜感激。非常感谢。

3 个答案:

答案 0 :(得分:10)

如果您打算做一个简单的grep,您可以取消附加步骤并在awk中进行过滤,例如:

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

但是,如果你打算做更多的事情,那么就像chepner already pointer out一样,你确实可以从awk内部进行管道传输。例如:

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

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


(根据您的评论)计算每个偶数行中的字符数,请尝试:

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

答案 1 :(得分:7)

您可以直接从awk内部管道输入:

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

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

(选择的答案对于手头的任务更好,但我会在这里留下这个答案作为将print语句传递给外部命令的示例。)

答案 2 :(得分:1)

为了使您的管道输出按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.本质上,它减去数字从行的长度中留下不需要的字符,留下想要的字符数作为结果。