awk
次のコマンドと同じ機能を達成したいと思います。
awk -F ";" '{print $3 > "/" $1 "/" $2}' file
たとえば、
入力として2行のファイルがあります。
path1;filename_1;f3_1
path2;filename_2;f3_2
私が望む出力は次のとおりです。
- ファイルの
/path1/filename_1
内容は次のとおりです。f3_1
- ファイルの
/path2/filename_2
内容は次のとおりです。f3_2
awkを使用してこれを実行すると、141終了コードSIGPIPEが表示されます。このエラーをバイパスしたいです。
答え1
awk
ファイルハンドルが不足しているようです。最新バージョンにアップグレードできない場合、awk
最も明確な回避策はそのファイルを使用してからそのファイルを閉じることです。
path;filename
複数回発生する可能性のある組み合わせはありますか?
そうでない場合は、以下を試してください。
awk -F ";" '{f="/"$1"/"$2; print $3 > f ; close(f)}' file
そうでなく>> f
既存のファイルに追加できる場合は、次を使用します。
awk -F ";" '{f="/"$1"/"$2; print $3 >> f ; close(f)}' file
ファイルを最初に作成するときにカットする必要がありますが、それ以降に追加する必要がある場合、状況は少し複雑です。
awk -F ";" '{ f="/"$1"/"$2;
if ( !fnames[f]++ ) { print > f };
print $3 >> f;
close(f)
}' file
連想fnames
配列は、スクリプトがファイル名を解決したかどうかを判断するために使用されます。そうでない場合は、ファイルを切り捨てます。
答え2
awk
私の考えでは、これはその機能と完全に一致しているので、愚かなことです。awk
次のことができます(bash-4.3
構文)。
(unset fds; typeset -A fds
while IFS=';' read -r a b c rest; do
file=/$a/$b
[[ ${fds[$file]} ]] || exec {fds[$file]}> "$file"
printf '%s\n' "$c" >&"${fds[$file]}"
done < file)
しかし、これは効率を低下させます(シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?awk
)、この問題を解決することができ、あまりにも多くの場合、同時に開いているファイルの数に制限を置くいくつかの実装とは対照的です。
または、次のこともできます(POSIXsh
構文)。
while IFS=';' read -r a b c rest; do
printf '%s\n' "$c" >> "/$a/$b"
done < file
ただし、これはファイルを上書きするのではなく、ファイルにテキストを追加します(そしてそれでも使用するよりもはるかに効率的ではありませんawk
)。
この操作も実行できますが、ファイルを開き、fdリストを手動で維持する作業をやり直すperl
必要があります。awk
perl -F ';' -lane '
$file = "/$F[0]/$F[1]";
unless (defined $fds{$file}) {
open $fds{$file}, ">", $file or die "$file: $!\n";
}
print {$fds{$file}} $F[2]' < file
(同時ファイルを開く制限と同じ潜在的な問題があります)。
答え3
使用カット:
while read -r line ; do printf "in the file /%s/%s the content is %s\n" $(echo $line | cut -d';' -f1) $(echo $line | cut -d';' -f2) $(echo $line | cut -d';' -f3) ; done < file
短いバージョン(Stéphane Chazelasの答えからいくつかのコンテンツを盗む)と結果を保存するために出力を別のファイルにリダイレクトする方法もあります。
while IFS=';' read -r f1 f2 f3 ; do printf "in the file /%s/%s the content is %s\n" $f1 $f2 $f3 ; done < files > file2