
次のモデルに従ったファイル名があります:
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg
cut
Unix のコマンドを使用して上記の文字列を切り取り、文字列から値を取得し211
て222
エコーする必要があります。
私はすでに grep を使用していますgrep -o -E '[0-9]+'
が、これに代わるものが必要です。
答え1
のような単純なツールではなく、標準的なテキスト処理ツールを使用する方がよいでしょうcut
。
以下にいくつかの方法を示します。
を使用するとawk
、_
または で.
区切られた最後から 2 番目のフィールドを取得できます。
awk -F '[_.]' '{print $(NF-1)}' file.txt
grep
PCRE ( -P
) の場合:
grep -Po '\d+(?=[^_]*$)' file.txt
-o
一致した部分のみを取得します\d+
1つ以上の数字に一致するゼロ幅の正の先読みは、行の最後まで
(?=[^_]*$)
何も続かないことを保証する。_
とsed
:
sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
.*_
最後まですべて一致_
([[:digit:]]+)
必要な数字と一致し、キャプチャされたグループに入れます.*
残りと一致する置換では、捕捉されたグループのみ
\1
が使用される。
の場合、とperl
同じロジックになりますsed
。
perl -pe 's/.*_(\d+).*/$1/' file.txt
を使用する必要がある場合はcut
、2 つの手順で実行し、最初に_
分離された 4 番目のフィールドを取得し、次に.
分離された 1 番目のフィールドを取得します。
cut -d_ -f4 file.txt | cut -d. -f1
フィールド番号をハードコードする必要があるため、これはお勧めできません。
文字列の場合は、シェル パラメータ展開を使用して実行します。
% str='1.raw_bank_details_211.trg'
% str=${str##*_}
% echo "${str%%.*}"
211
構文を使用しwhile
て各行を変数に入れてこれを行うこともできますが、大きなファイルの場合は遅くなります。また、代わりに_.
を として使用し、必要に応じてIFS
ハードコードされたフィールド ( など) を取得することもできます。cut
例:
% cat file.txt
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg
% awk -F '[_.]' '{print $(NF-1)}' file.txt
211
222
% grep -Po '\d+(?=[^_]*$)' file.txt
211
222
% sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
211
222
% perl -pe 's/.*_(\d+).*/$1/' file.txt
211
222
% cut -d_ -f4 file.txt | cut -d. -f1
211
222
答え2
cut
は、そのためのツールとしては適切ではありません。ファイル名などの短い文字列を操作するには、可能な限りシェルの文字列操作機能を使用してください。すべてのsh型シェル¹(sh、dash、bash、ksh、zsh、…)には、変数置換の一部として基本的な文字列操作機能があります。たとえば、ダッシュマニュアル「パラメータ拡張」の下で、パターンに一致する最短/最長のプレフィックス/サフィックスを削除できます。
ファイル名の最後の数字のシーケンスが必要なので、次のようになります。
- 最後の桁まですべてを削除して、数値以外の接尾辞を決定します。
- その接尾辞を削除します。
- 最後の非数字まですべてを削除します。
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"
¹一部の POSIX 以前の Bourne シェルを除きますが、それらについては気にする必要はありません。