各行に 1 つのファイル名が含まれるテキスト ファイルがあります。
111_c4l5r120.png
123_c4l4r60.png
135_c4l4r180.png
147_c4l3r60.png
15_c4l1r120.png
...
これを次の形に変換します:
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
...
このコードを使用します:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "$line" >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"
しかし、結果は次のようになります。
111_c4l5r120.png
111
123_c4l4r60.png
123
135_c4l4r180.png
135
147_c4l3r60.png
147
15_c4l1r120.png
15
...
希望する出力を得るにはスクリプトをどのように変更すればよいでしょうか?
答え1
シェルでこのような操作をしないでください。必要以上に複雑で、エラーが発生しやすく、非常に遅くなります。このようなテキスト操作用に設計されたツールは多数あります。たとえば、sed
(ここでは の最近の GNU または BSD 実装を想定しています-E
)では、次のようになります。
$ sed -E 's/([^_]*).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
または、任意のsed
:
$ sed 's/\([^_]*\).*/& \1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
パール:
$ perl -pe 's/(.+?)_.*/$& $1/' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
awk:
$ awk -F_ '{print $0,$1}' file
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15
答え2
シェルを使用する特別な理由がない限り、テルドンの答えより良い代替案を提供します。
bash
スクリプトのシェバンに示されているように、次のように使用しているため、-n
エコーするオプションを使用できます。
echo -n "${line} " >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt
または、 を使用せずにシェルの機能を使用して行を処理することもできますcut
。
echo "${line} ${line%%_*}" >> output.txt
(両方のecho
行を置き換えます)。
あるいは、printf
これも効果的です。POSIX シェル、そして一般的にはより良いです(なぜ printf は echo よりも優れているのでしょうか?詳細については):
printf "%s " "${line}" >> output.txt
echo "$line" | cut -d'_' -f 1 >> output.txt
または
printf "%s %s\n" "${line}" "${line%%_*}" >> output.txt
(厳密に言えば、平易に言えば/bin/sh
、echo -n
持ち運びできない明示的に使用しているため、bash
ここでは問題ありません。
答え3
はい、どうぞ:
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "$line" `echo "$line" | cut -d'_' -f 1` >> output.txt
# echo "$line" | cut -d'_' -f 1 >> output.txt
done < "$1"
出力:
$ rm -rf output.txt
$ ./test.sh 1.1; cat output.txt
111_c4l5r120.png 111
123_c4l4r60.png 123
135_c4l4r180.png 135
147_c4l3r60.png 147
15_c4l1r120.png 15