文字列があり、その区切り文字が?
であるとします。
Leslie Cheung April 1 ? Elvis August 16 ? Leonard Nimoy February 27
区切り文字の間の最初の部分文字列をgrep
する方法を知っています。
echo $above_string | grep -oP "^[^?]*"
Leslie Cheung April 1
2番目または3番目の部分文字列をgrepするには、どのように正規表現を変更する必要がありますか?
echo $above_string | grep -oP "^([^?]*\?){2}\K[^?]*"
N番目の文字列を取得するには、2
をn - 1
値に変更します。
これは、n番目の文字列その行が必要であることを前提としています。 n-1個の文字列があり、?
がリテラル「?」で終了していない(\?
はPerl正規表現の特殊文字であるため)。次に、\K
を使用すると、前のコンテンツには興味がないと述べ、次の区切り文字まで次のテキストのみを抽出します。
カットの使い方は? 2番目のパターンを印刷する場合
echo "$above_string" | cut -f2 -d "?"
2列目以降
echo "$above_string" | cut -f2- -d "?"
Awkを使用して、改行で区切られた2番目と3番目のレコードを印刷します。
awk -F"?" '{printf "%s\n%s\n", $2,$3}'
Elvis August 16
Leonard Nimoy February 27
レコードを交換したい場合は、変数として設定できます。
awk -v record=2 -F"?" '{print $record}'
Elvis August 16
sed
を使用すると、次のことができます。
sed '/\n/P;//d;s/[^?]*/\n&\n/[num];D'
...上記の[num]
を、目的の発生を表す数値に置き換えます。
次の例に示すように、指定した番号の付いたオカレンスが存在しない場合、sed
は何も出力しません。
echo ,2,3 | sed '/\n/P;//d;s/[^,]*/\n&\n/4;D'
ゼロ以上の非コンマ文字のシーケンスの最初の一致の上には、最初のコンマの前に出現するゼロ文字があります。 2つ目は2
で、3つ目は3
です。そのパターンは4回目に出現しないため、置換は成功しません。
また、すべてのsed
が右側の置換フィールドで\n
改行エスケープをサポートするわけではないため、エスケープ文字列のn
文字をリテラル改行で置き換える必要がある場合もあります。 。
sed '/\n/P;//d;s/[^?]*/\
&\
/[num];D'
あなたの文字列でそれはします:
str='> Leslie Cheung April 1 ? Elvis August 16 ? Leonard Nimoy February 27'
for o in 1 2 3
do printf %s\\n "$str" |
sed "/\n/P;//d;s/[^?]*/\n:$o:&\n/$o;D"
done
...これは、for
ループを3回実行してsed
ループを3回実行して、3つすべての[^?]*
を一致させて出力します...
:1:> Leslie Cheung April 1
:2: Elvis August 16
:3: Leonard Nimoy February 27
...または$o
の値ごとに1つ。
これを少し拡張して、次のような[num]
not-nullの発生をスキップできます。
i=
until [ "$((i+=1))" -gt 10 ] &&
printf %s\\n "$str"
do printf %s ":$i:$str?"; done |
sed '/..*\n?*/P;s///;s/[^?]*/\n&\n/7;D'
...印刷する...
:3:> Leslie Cheung April 1
Elvis August 16
Leonard Nimoy February 27
:10:> Leslie Cheung April 1
包括的にすることもできます。例えば:
printf %s\\n "$str?$str" |
sed '/.*\n[^_[:alnum:]]*/P;s///
s/[_[:alnum:]]\{1,\}/\n&\n/3;D'
...これは、2つの文字列を連結して、英数字と_
文字の3番目の非ヌルシーケンスごとに別々の行にそれぞれを出力します...
April
August
Nimoy
Leslie
1
16
February
これにはsedを使用できますが、お勧めできません。量指定子を使用して目的のフィールドを選択するゼロベースのソリューションを次に示します。
n=1
sed 's/\([^?]*? *\)\{'$n'\}//; s/?.*//' <<<"$above_string"
出力:
Elvis August 16