打印奇数行,打印偶数行


18

我想从文件中打印奇数行和偶数行。

我发现了这个利用echo的shell脚本。

#!/bin/bash
# Write a shell script that, given a file name as the argument will write
# the even numbered line to a file with name evenfile and odd numbered lines
# in a text file called oddfile.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------

file=$1
counter=0

eout="evenfile.$$" # even file name
oout="oddfile.$$" # odd file name

if [ $# -eq 0 ]
then
    echo "$(basename $0) file"
    exit 1
fi

if [ ! -f $file ]
then
    echo "$file not a file"
    exit 2
fi

while read line
do
    # find out odd or even line number
    isEvenNo=$( expr $counter % 2 )

    if [ $isEvenNo -ne 0 ]
    then
        # even match
        echo $line >> $eout
    else
        # odd match
        echo $line >> $oout
    fi
    # increase counter by 1
    (( counter ++ ))
done < $file
echo "Even file - $eout"
echo "Odd file - $oout"

但是,没有一种方法可以做到这一点吗?

是的,请阅读awk

偶数行:

awk 'NR % 2' filename

奇数行:

awk 'NR % 2 == 1' filename

但这对我不起作用。根据差异,两者都产生相同的输出。与原始文件相比,它们实际上的长度都是原来的一半,并且都包含奇数行。难道我做错了什么?


6
第一个应该是NR % 2 == 0,否则等于第二个。
enzotib

似乎有几份在线文档(包括这份文档)显示在搜索的顶部,该文档指出NR%2为您提供了偶数行,这是不正确的,因为1%2 = 1,它给了您奇数。 = true,2%2 = 0 = false。
deltaray 2012年

Answers:


12

如您所问“一行”:

awk '{print>sprintf("%sfile.%d",NR%2?"odd":"even",PROCINFO["pid"])}' filename

请注意,大多数代码是由于您选择了精美的输出文件名所致。否则,以下代码足以将奇数行放在“ line-1”中,并将偶数行放在“ line-0”中:

awk '{print>"line-"NR%2}' filename

26

我希望尽可能与POSIX兼容,因此我想发布这种替代方法。我经常使用它们来处理xargs流水线之前的文本。

打印偶数行

sed -n 'n;p'

打印奇数行

sed -n 'p;n'

尽管我经常使用awk,但对于这种类型的任务而言,它实在太过分了。


14

这很容易:

 sed -n 2~2p filename

从文件名中打印偶数行

sed -n 1~2p filename

将打印奇数行。


1
+1,因为不会多余地使用AWK。不是POSIX sed,但这仍然是可靠的方法。
JM Becker 2012年

@TechZilla我不理解“多余地使用AWK”-awk也是POSIX。
jw013 2012年

3
@ jw013:没什么问题awk,我个人经常使用它。我从没说过什么是“不是POSIX” awk,而是指答案的sed选项。特别是~运算符,它是GNU扩展,对于许多人来说仍然可以接受。对于“ AWK多余地使用AWK , I personally believe using ”这一简单任务而言,这是过分的。因此,+1是用于完成任务的sed,它的实用程序比轻awk
JM Becker 2012年

1
有人可以在这里解释〜运算符如何工作吗?
永远的学习者

9

对于偶数,代码应为

awk 'NR%2==0' filename

&为奇数

awk 'NR%2==1' filename

1
这是完美的。即使您需要获得以10为增量的行也可以,例如,您需要将大小为100万的有序文件减少到100k。这正是我想要的。
德克斯特(Dexter)

如何在AWK中打印偶数列?我不能使这个工作gawk 'FS=",";NF%2==0' file.csv
hhh

2

您只需一次sed调用即可完成操作,而无需两次读取文件:

sed '$!n
w even
d' infile > odd

或者,如果您更喜欢一行:

sed -e '$!n' -e 'w even' -e d infile > odd

请注意,如果文件仅包含一行(这些行将被w写入,even而不是odd因为第一行n未执行),则这些将无法获得预期的结果。为了避免这种情况,请添加一个条件:

sed -e '$!n' -e '1!{w even' -e 'd}' infile > odd

怎么运行的 ?好吧,它使用了三个sed命令:
n-如果不在最后一行,将模式空间打印stdout(将重定向到file odd),将其替换为下一行(因此现在它正在处理偶数行)并继续执行其余命令
w-追加模式空间到文件even
d-删除当前模式空间并重新启动循环-这样做的副作用是,sed永远不会自动打印模式空间,因为它永远不会到达脚本结尾

换句话说,n仅在奇数行执行,并且wd仅在偶数行中执行。sed除非我输入的内容仅由一行组成,否则永远不会进行自动打印。


您能详细说明一下它是如何工作的吗?
永远的学习者

非常感谢don_crissti的帮助。真诚的感谢,也赞不绝口。
永远的学习者

0

尝试这个:

awk '{if(NR%2){print $0 > "odd.file"}else{print $0 > "even.file"}}' filename

您确定要输出记录号吗?
manatwork 2011年

对此感到抱歉,我对其进行了修改以输出整行。
renma 2011年

0

我会选择,perl因为我喜欢perl

perl -pe 'BEGIN{open($e,">even_lines");open($o,">odd_lines")} $. % 2 ?select $o:select $e;'

使用-p隐式打印的事实来复制其sed工作方式-我们使用它select来选择要写入的文件句柄。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.