奇数行を印刷し、偶数行を印刷します


18

ファイルから奇数行と偶数行を印刷したい。

エコーを利用するこのシェルスクリプトを見つけました。

#!/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"

しかし、1行で行う方法はありませんか?

はい、awkを使用してください。

偶数行:

awk 'NR % 2' filename

奇数行:

awk 'NR % 2 == 1' filename

しかし、私にはうまくいきません。diffによると、どちらも同じ出力を生成します。元のファイルと比較すると、これらは両方とも実際には半分の長さであり、両方とも奇数行が含まれています。私は何か間違っていますか?


6
最初のものはである必要がありNR % 2 == 0、そうでない場合は2番目のものと同等です。
エンゾチブ

オンラインでいくつかのドキュメント(このドキュメントを含む)が検索の上部に表示され、NR%2が偶数行を提供することを示していますが、これは正しくありません。1%2 = 1 =真、2%2 = 0 =偽。
デルタレイ

回答:


12

「1行で」と尋ねたように:

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ベッカー

@TechZilla「外部からAWKを使用する」ことは理解できません。awkもPOSIXです。
jw013

3
@ jw013:何も問題はありませんがawk、個人的には頻繁に使用しています。私は何かについて「POSIXではない」と言ったことは一度もありませんawkでしたが、答えのsed選択肢について言及していました。具体的には~演算子であり、これはGNU拡張機能であり、多くの人が受け入れています。, I personally believe using この単純なタスクに「AWKを外部からawkを使用する」ことはやり過ぎです。だから+1はでタスクを完了するためのsedものawkでした。
JMベッカー

1
誰かが〜演算子がここでどのように機能するか説明してください
永遠に学習者

9

偶数の場合、コードは

awk 'NR%2==0' filename

&奇数の場合

awk 'NR%2==1' filename

1
これは完璧です。10単位で行を取得する必要がある場合でも、サイズが100万から100kの順序付けされたファイルを削減する必要がある場合でも機能します。これはまさに私が欲しかったものです。
デクスター

AWKで偶数列を印刷するにはどうすればよいですか?私はこれを働かせることができませんgawk 'FS=",";NF%2==0' file.csv
hhh

2

1回のsed呼び出しで実行でき、ファイルを2回読み込む必要はありません。

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

または、1行で希望する場合:

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

ファイルは一行を含む場合、これらは、期待される結果が得られないことに注意してくださいは、(行をするwにritten even代わりのodd最初としてn実行されません)。それを回避するには、条件を追加します。

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

使い方 ?さて、それは3つのsedコマンドを使用します:
n-最後の行にない場合はパターンスペースを印刷stdout(ファイルにリダイレクトされますodd)、次の行に置き換えて(したがって、偶数行を処理しています)残りのコマンドの実行を続けます
w-追加ファイルへのパターンスペースeven
d-現在のパターンスペースを削除してサイクルを再開します-これの副作用はsed、スクリプトの最後に到達しないため、パターンスペースが自動印刷されないことです。

換言すれば、n奇数ラインのみで実行され、w及びd偶数ラインのみで実行されます。sed私が言ったように、入力が単一の行で構成されていない限り、自動印刷はできません。


どのように機能するのか詳しく説明していただけますか?
永遠に学習者

don_crisstiに感謝します。心から感謝します。
永遠に学習者

0

これを試して:

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

レコード番号を出力してもよろしいですか?
マナトワーク

申し訳ありませんが、行全体を出力するように変更しました。
レンマ

0

私は一緒に行くだろうperl、私は好きなのでperl

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

-p暗黙的に印刷するという事実を使用して、複製された方法を複製しますsed-そして、selectどのファイルハンドルに書き込むかを選択するために使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.