2016-08-20 5 views
0

これが可能かどうかわかりませんが、ここではわかります-ファイルから複数の行を一度に取り出す

私は数字のリストを持っています。

cat list 

出力 -

1 
22 
53 
75 

そして、私は500行(file.txtなど)とセカンダリファイルを持っています。 そのファイルから第1、第22、第53、第75行を選びたいと思います。私は現在、

for i in `cat list`; do awk "NR==$i" file.txt ; done 

これは動作しますが、それは(私の実際のファイルは50K +のラインを持っている)本当に遅いですが - 試してみた何

。 より効率的なソリューションがあるのか​​どうか疑問に思っていました。おそらく、リストを読んで、4つのプロセスではなく、1つのプロセスですべての行を引き出す方法です。

+0

'sedの-n -e '1P' '53P' -e '75P' filename' -e -e '22P' 非常に小さい場合、別のawkです。または、 '$ listのiのためにループする。 sed -n "$ {i} p" file.txtを実行します。 done' –

+0

'list'がファイル(例えば' list.txt')であれば 'read -r num while 'を使います。 sed -n "$ {num} p" file.txtを実行します。 done "" $ list.txt "' –

答えて

5

のリストは、これらの行が含まれているとしましょう:

$ cat list 
1 
22 
53 
75 

+ sedのはbashベースのアプローチ:

$ a=($(<list)) 
# ^^ a will contain contents of 'list' in individual array elements. 
$ sed -n "${a[*]/%/p;}" file.txt 
# ^^ "${a[*]/%/p;}" will expand to "1p;22p;53p;75p;" 

awkに基づくアプローチ:

$ awk 'NR==FNR{a[$0]++; next;} (FNR in a)' list file.txt 
# Array 'a' will contain 1 at indices equal to lines in 'list' 
# Then match line numbers for second file, which are indices of 'a' 
+0

ありがとうございました。私は実際にtail -n |それがより速くなることが判明して以来、ヘッド・アンド・アプローチを採用している。 – VM17

+0

'tail | head 'は1行で高速です。しかし、私はそれが行のリスト(そしてそれによってbashのforループ)のためにどのように運賃を得るのか分からなかった。 – anishsane

+1

上記のawkスクリプトはこれを行うための唯一の方法です。他のどのアプローチよりも堅牢で移植性があり、数桁も高速になります。[なぜシェルを使ってループを処理するかをテキストで判断する](http://unix.stackexchange.com/questions/169716/whyis-using-a-shell)を参照してください。 -loop-to-process-text-consider-bad-practice)を使用して、ループを回避する理由がいくつかあります。 –

-1

これを実現するにはheadtailを使用できます。

cat file | head -n 5 | tail -n 1 

はトリックを行う必要があります:私はライン5を取得したいので、もし

USNGヘッドは、ファイルの最初ののn行が返されます、尾は、最後ののn行を返します。

ETA - パラメータとして0を渡すことはできないことを指摘しておきましょう.nオプションには0を上書きし、1行以上は0以上を指定します。

希望します。

+2

'head'と' tail'はファイル入力を受け入れることができます。これはcatの役に立たない使い方です。 'head -n 5 file | tail -n 1' – Sundeep

1

GNU SEDとGNUのbashの場合:

sed -n -f <(sed 's/.*/&p/' numbers.txt) file.txt 
ここ
+1

'-f'は私の' bash + sed'アプローチに比べて素晴らしいアイデアでした。より大きい 'number.txt'ファイル(' MAX_ARG_STRLEN'を越えないので)で動作します。 – anishsane

0

リストは

awk -v nums="^($(paste -s -d"|" list))$" 'NR~nums' file 
関連する問題