16

我想打印奇数行(1,3,5,7..)而不做任何更改,但偶数行(2,4,6,8)处理以grep开头的管道。我想将所有内容写入新文件(奇数行没有任何更改,偶数行的新值)。

我知道如何在 awk 中打印每一行:

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

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

建议将不胜感激。非常感谢。

4

3 回答 3

15

如果您打算做一个简单的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
于 2012-07-19T12:19:16.880 回答
8

您可以直接从内部管道awk

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

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

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

于 2012-07-19T12:13:12.300 回答
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。本质上,它从离开的行的长度中减去不需要的字符数结果是想要的字符数。

于 2012-07-19T13:58:33.487 回答