
.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
どんなアイデアがありますか?
答え1
ksh93/bash/zshで単純なfor
ループとパラメータ拡張を介して:
for f in *-QTR*.tsv
do
grep 8-K < "$f" > "${f:0:4}"Q"${f:8:1}".txt
done
今回はgrep
、ファイル(ファイル名に「-QTR」とファイル名の末尾に「.tsv」が必要なワイルドカードパターンに基づいてファイルリストが生成されます)を実行すると、出力がファイルにリダイレクトされます。名前に基づいて慎重に構成されています。
- ファイル名の最初の4文字 - 年
- この手紙
Q
- ファイル名の9番目の文字 - Quarter
答え2
必須POSIXsh
バリアント:
#! /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"
答え3
その他のオプション
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)
答え4
明示的なループを回避するには、次の回避策があります。たぶん誰かがそれを改善することができます。こんな感じです。
ls -1 *.tsv | xargs -n1 -I'{}' bash -c 'f="{}";grep 8-K $f > ${f//[^0-9Q]/}.txt'
- エルエス処理したいファイルのみを一覧表示
- パラメータこれらの各ファイルを1つずつ処理します(-n1)
- ㅏ強く打つ文字列を処理できるようにシェルを起動します(ポイント5を参照)。
- ファイル名を変数に設定$f
- ${f//[^0-9Q]/}.txtファイル名に不要な文字を削除します(これはあなたの例にのみ当てはまります)。
利点: - シンプルなワンライナー
欠点: - 処理されたファイルごとにbashプロセスを開始します。
Bashを使用しない同様の解決策があるかもしれませんが、よくわかりません。