您现有的 gawk one-liner 非常接近。这里它被格式化为更易读的脚本:
FNR == 1 {
if (o)
close(o)
o = FILENAME
sub(/\.txt/, "_oddlines.txt", o)
}
{
NR % 2 == 1
print > o
}
这应该使错误显而易见1。所以现在我们删除了那个错误:
FNR == 1 {
if (o)
close(o)
o = FILENAME
sub(/\.txt/, "_oddlines.txt", o)
}
NR % 2 == 1 {
print > o
}
$ awk -f foo.awk *.txt
它可以工作(当然你可以重新单行化它)。
(通常我会像其他答案一样使用for 来执行此操作,但我想向您展示您有多接近!)
1每条评论,可能不是很明显?
Awk 的基本语言结构是“模式-动作”语句。 awk program 只是这些语句的列表。 “模式”之所以如此命名,是因为最初它们大多是类似 grep 的正则表达式模式:
$ awk '/^be.*st$/' < /usr/share/dict/web2
beanfeast
beast
[snip]
(除了斜线,这基本上只是运行grep,因为它使用默认操作print。)
模式实际上可以包含两个地址,但更典型的是使用一个,例如在这些情况下。不包含在斜线内的模式允许像 FNR == 1(File-specific Nnumber of this Record 等于 1)或 NR % 2 == 1(Nnumber of this Record—cumulative跨所有文件!-mod 2 等于 1)。
不过,一旦您打开大括号,您就进入了“动作”部分。现在NR % 2 == 1 只需计算结果(真或假),然后将其丢弃。如果您完全省略“模式”部分,则“动作”部分将在 每个 输入行上运行。所以这会打印每一行。
请注意,测试NR % 2 == 1 正在测试累积 记录号。因此,如果某个文件的行数为奇数(“记录”),则下一个文件将打印出每一行 偶数 行(这将持续到您遇到另一个行数为奇数的文件)。
例如,假设两个输入文件是A.txt 和B.txt。 awk 开始读取A.txt,并将第一行的FNR 和NR 都设置为1,例如file A, line 1。由于FNR == 1 第一个“动作”已经完成,设置o。然后 awk 测试第二个模式。 NR 是 1,所以 NR % 2 是 1,所以第二个“动作”完成,将该行打印到 A_oddlines.txt。
现在假设文件A.txt 只包含那一行。 awk 现在继续归档B.txt,重置FNR,但留下NR 累积。 B 的第一行可能是 file B, line 1。 awk 尝试第一个“模式”,实际上是FNR == 1,所以这会关闭旧的o 并设置新的。
但是NR 是2,因为NR 在所有 输入文件中是累积的。所以第二个模式(NR % 2 == 1)计算2 % 2(即0)并比较== 1,这是错误的,因此awk跳过文件B.txt的第1行的第二个“动作”。第 2 行,如果存在,将有 FNR == 2 和 NR == 3,因此该行将被复制出来。
(我最初认为,由于您的脚本接近工作,您打算这样做并且只是在语法上卡住了一点。)