前回の最後に少しやりましたが、ファイルパスと行番号のリストから、該当する行を抽出してみます。
listは前回同様このようにファイル名と行番号が格納されています。
takk@deb9:~/tmp$ head list x00:40 x00:72 x00:87 x01:25 x01:32 x01:36 x02:27 x02:60 x02:92 x04:17 takk@deb9:~/tmp$
各ファイル。
takk@deb9:~/tmp$ ls x00 x01 x02 x03 x04 x05 x06 x07 x08 x09 takk@deb9:~/tmp$
まずは、bashの変数置換でファイル名と行番号をsedに指定して、行抽出する方法。
takk@deb9:~/tmp$ for i in `cat list`;do fn=${i%%:*};no=${i##*:};sed -ne ${no}p $fn;done parrakeet barraged parrakeets irritatingly deterring borrowed irresistible surrounds harried Barr's guerrilla's Lorraine's irregularity's surrealism's Corrine diarrhoea's scarred stirrer's barren Barrie's takk@deb9:~/tmp$
長くて分かりづらい。なるべく使いたくない書き方です。
次も似たような感じですが、bashの配列を用いる方法。先ほどと同じ結果になります。
takk@deb9:~/tmp$ for i in `<list`;do a=(`tr : " " <<< $i`);sed -ne ${a[1]}p ${a[0]};done
これも分かりづらいし、括弧が多いのは間違いの元です。
もう少し簡潔にしたもの。
takk@deb9:~/tmp$ for i in `<list`;do sed -ne ${i##*:}p ${i%%:*};done
どうしてもbash変数使わなければならない時に、使うかもしれません。
次はsed in sed。sedの中でsedが登場します。覚えやすいし、私は一番使うかも。
takk@deb9:~/tmp$ sed -r 's/^(.*):(.*)$/sed -ne \2p \1/' list sed -ne 40p x00 sed -ne 72p x00 sed -ne 87p x00 sed -ne 25p x01 sed -ne 32p x01 sed -ne 36p x01 sed -ne 27p x02 sed -ne 60p x02 sed -ne 92p x02 sed -ne 17p x04 sed -ne 11p x05 sed -ne 16p x05 sed -ne 23p x05 sed -ne 60p x05 sed -ne 87p x05 sed -ne 52p x06 sed -ne 14p x07 sed -ne 16p x09 sed -ne 57p x09 sed -ne 87p x09 takk@deb9:~/tmp$
sedでsedのリストを作った後は、それを実行すれば、該当行が抽出できます。
takk@deb9:~/tmp$ sed -r 's/^(.*):(.*)$/sed -ne \2p \1/' list | sh parrakeet barraged parrakeets irritatingly deterring borrowed irresistible surrounds harried Barr's guerrilla's Lorraine's irregularity's surrealism's Corrine diarrhoea's scarred stirrer's barren Barrie's takk@deb9:~/tmp$
sedでできるなら、perlでもできますね。オプションで自動で配列@Fに格納されるので、スクリプトが短くできます。[]が好きであれば使うのですが、[]よりもやわらかい印象の()が好きなので、いまいち。
takk@deb9:~/tmp$ perl -F/:/ -pale '$_="sed -ne $F[1]p $F[0]"' list
最後は、awk。列分離はawkの得意技ですね。なんだかんだ一番分かりやすいかもしれません。
takk@deb9:~/tmp$ awk -F: '{printf "sed -ne %sp %s\n",$2,$1}' list
コメント