web-dev-qa-db-ja.com

毎回異なるファイル名にリダイレクトする複数のファイルをGrepする

.tsvファイルでいっぱいのディレクトリがあり、それらのそれぞれに対してgrepコマンドを実行して、テキスト行の特定のグループを引き出し、それを同様のファイル名で関連するテキストファイルに保存します。たとえば、ファイルの1つだけをgrepする場合、grepコマンドは次のようになります。

grep -h 8-K 2008-QTR1.tsv > 2008Q1.txt

しかし、私は次のようなtsvファイルのリストを持っています:

2008-QTR1.tsv
2008-QTR2.tsv
2008-QTR3.tsv
2008-QTR4.tsv
2009-QTR1.tsv
2009-QTR2.tsv
2009-QTR3.tsv
...

そして、grepした後、次のように保存する必要があります。

2008Q1.txt
2008Q2.txt
2008Q3.txt
2008Q4.txt
2009Q1.txt
2009Q2.txt
2009Q3.txt

何かご意見は?

11
jtyun

Ksh93/bash/zshでは、単純なforループとパラメーター展開を使用します。

for f in *-QTR*.tsv
do 
  grep 8-K < "$f" > "${f:0:4}"Q"${f:8:1}".txt
done

これは、一度に1つのファイルに対してgrepを実行します(そのファイルのリストは、ファイル名に「-QTR」が存在し、ファイル名の末尾に「.tsv」が存在する必要があるワイルドカードパターンから生成されます)、以下に基づいて慎重に作成されたファイル名に出力をリダイレクトします。

  • ファイル名の最初の4文字-年
  • 文字Q
  • ファイル名の9番目の文字-四半期
12
Jeff Schaller

必須のPOSIX shバリアント:

#! /bin/sh -
ret=0
for file in [[:digit:]][[:digit:]][[:digit:]][[:digit:]]-QTR[1234].tsv; do
  base=${file%.tsv}
  grep 8-K < "$file" > "${base%%-*}Q${base##*-QTR}".txt || ret=$?
done
exit "$ret"
5

別のオプション

for f in  200{8..9}-QTR{1..4}.tsv; do
    grep "pattern" $f > $(sed "s/[-RTtsv]*//g" <<< $f)txt;
done

チュートリアル:ファイル名のリストを作成する展開を設定する

200{8..9}-QTR{1..4}.tsv

に拡大する

2008-QTR1.tsv 2008-QTR2.tsv 2008-QTR3.tsv 2008-QTR4.tsv 2009-QTR1.tsv 2009-QTR2.tsv 2009-QTR3.tsv 2009-QTR4.tsv

そして、毎年、そして今までの四半期は、

20{08..19}-QTR{1..4}.tsv

リストを反復するfor..do..done、探しているパターンをファイルから抽出します

grep "pattern" $f

そして、sedで不要な文字を削除し、txtサフィックスを追加することによって形成された新しいファイル名にリダイレクトします。

$(sed "s/[-RTtsv]*//g" <<< $f)txt

または

$(sed "s/[-RT]*//g" <<< ${f%%.*}.txt)
2
bu5hman

明示的なループを回避したい場合は、次の解決策があります。誰かがそれを改善できるかもしれません。こんな感じです。

ls -1 *.tsv | xargs -n1 -I'{}' bash -c 'f="{}";grep 8-K $f > ${f//[^0-9Q]/}.txt'
  1. ls処理するファイルを一覧表示するだけです
  2. xargsこれらの各ファイルを1つずつ処理する(-n1
  3. a bash文字列を処理できるようにシェルが起動されます(ポイント5を参照)
  4. ファイル名を変数に設定します$ f
  5. $ {f // [^ 0-9Q] /} .txtファイル名に不要な文字をすべて削除します(これは、例に固有です)

長所:-シンプルなワンライナー

短所:-処理されるファイルごとにbashプロセスが開始される

多分bashを使用せずに同様の解決策がありますが、私はそれを知りません(たとえば、evalはこのコンテキストでは機能しないはずです)

0
Jacques