カット/感嘆符を区切り記号として使用

カット/感嘆符を区切り記号として使用

Bash以外のシェルには、解析したい次の文字列があります。

stringhere/morestring!99

99解析後に文字列の末尾を保持し、残りの文字列を削除したいと思います。

保持する必要がある部分文字列の長さは常に2文字ではありません。!文字列の終わりから1つ以上の数字または,

入力/出力の例:

In: stringhere/morestring!99
Out: 99

In: string/more!99,string/more!98,string/more!97
Out: 99

cut!文字列の中間を除いて、何かが明らかなように聞こえます。

見つけることができるショートカットがありますか?もっと良くなるかawk

答え1

文字列がFILEにあり、常に最初の!数字の後ろと前の最初の数字だけが必要な,場合は、その数字がある場合は機能します。

awk -F'[!,]' '{print$2}' FILE

!または、区切り文字として使用し、間の最初の数字または直後の,2番目のフィールドを表示します。!,! ,行の中や前に何もない場合。

,上記の最初の!awkの例が以前にあった場合は適用されません。

あるコマンドを別のコマンドにパイプすることもできますcut。最初にそれを!区切り文字として指定し、最初のコマンドの後にコンテンツをインポートし、次の!コマンドでそれを区切り文字として指定し、,最初のコマンドの前にコンテンツを取得します(,存在する場合)。

cut -d'!' -f2 FILE | cut -d',' -f1

答え2

使用できますが、cut2回のパスが必要です。最初は最初の後に来るものを取得し、!2番目はそれ以降のすべてを削除します,

$ echo 'string/more!99,string/more!98,string/more!97' | 
    cut -d'!' -f2- | cut -d, -f1
99

繰り返しますが、そうでない場合(,2番目のものはここでは必要ではなく、まったく同じコマンドが使用できることを示すために追加しました):cut

$ echo 'string/more!99' | cut -d'!' -f2- | cut -d, -f1
99

別のオプションは次のとおりですsed

$ echo 'string/more!99,string/more!98,string/more!97' | 
    sed -E 's/^[^!]+!([0-9]+).*/\1/'
99
$ echo 'string/more!99' | sed -E 's/^[^!]+!([0-9]+).*/\1/'
99

またはperl:

$ echo 'string/more!99,string/more!98,string/more!97' | 
    perl -pe 's/.+?!(\d+).*/\1/'
99
$ echo 'string/more!99' | perl -pe 's/.+?!(\d+).*/\1/'
99

またはGNUgrep

$ echo 'string/more!99,string/more!98,string/more!97' | 
    grep -oP '^[^!]+!\K\d+'
99
$ echo 'string/more!99' | grep -oP '^[^!]+!\K\d+'
99

答え3

必要なのはシェルの引数拡張構文だけです。これは以下にあります。

$ input='stringhere/morestring!99'
$ echo "${input#*!}"
99

その後#は、次のようなパターンが続きます。最短 プレフィックスこのパターンに一致する項目が削除されます。

$ input='string/more!99,string/more!98,string/more!97'
$ first=${input%%,*}
$ echo "${first#*!}"
99

その後%%は、次のようなパターンが続きます。最長 サフィックス一致するパターンが削除されます。


${var#pattern)- 最も短い一致プレフィックスを削除します。
${var##pattern)- 一致する最も長いプレフィックスを削除します。
${var%pattern)- 一致する最も短いサフィックスを削除します。
${var%%pattern)- 一致する最も長いサフィックスを削除します。

答え4

sed.GNUを使用sedして拡張正規表現を有効にすることもできます。

sed -E 's/^[^!]*!([0-9]+).*$/\1/'

または - より携帯性に優れています。

sed 's/^[^!]*!\([0-9]\{1,\}\).*$/\1/p'

!これは、「最初の数字の前のすべての項目、後ろの1つ以上の数字、そして後ろの行の終わりまでのすべての種類の文字が来る」パターンと一致し、行全体を「1つ以上の数字」部分にのみ置き換えます。

~> echo 'string/more!99,string/more!98,string/more!97' | sed -E 's/^[^!]*!([0-9]+).*$/\1/'
99

一致しない行がある場合は、次を使用してこれを抑制できます。

sed -nE 's/^[^!]*!([0-9]+).*$/\1/p'

代わりに。デフォルトでは、これは何も出力せず、一致するパターンが見つかった場合にのみ出力を印刷します。

関連情報