各行にファイル名を含むテキストファイルがあります。
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 -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
(スクリプトのshebangに示すように)を使用しているので、この-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