web-dev-qa-db-ja.com

指定された区切り文字の間のn番目の部分文字列をgrepする方法は?

文字列があり、その区切り文字が?であるとします。

Leslie Cheung April 1 ? Elvis August 16 ? Leonard Nimoy February 27

区切り文字の間の最初の部分文字列をgrepする方法を知っています。

echo $above_string | grep -oP "^[^?]*"
Leslie Cheung April 1

2番目または3番目の部分文字列をgrepするには、どのように正規表現を変更する必要がありますか?

3
Abdul Al Hazred
echo $above_string | grep -oP "^([^?]*\?){2}\K[^?]*"

N番目の文字列を取得するには、2n - 1値に変更します。

これは、n番目の文字列その行が必要であることを前提としています。 n-1個の文字列があり、?がリテラル「?」で終了していない(\?はPerl正規表現の特殊文字であるため)。次に、\Kを使用すると、前のコンテンツには興味がないと述べ、次の区切り文字まで次のテキストのみを抽出します。

4
Ángel

カットの使い方は? 2番目のパターンを印刷する場合

echo "$above_string" | cut -f2 -d "?"

2列目以降

echo "$above_string" | cut -f2- -d "?"

12
rahul

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 
4
jasonwryan

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
3
mikeserv

sed

これにはsedを使用できますが、お勧めできません。量指定子を使用して目的のフィールドを選択するゼロベースのソリューションを次に示します。

n=1
sed 's/\([^?]*? *\)\{'$n'\}//; s/?.*//' <<<"$above_string"

出力:

Elvis August 16 
2
Thor