文字列から部分文字列を抽出したいのですが、正規表現の末尾が繰り返されています。多くの言語の instr() 関数が最初のインスタンスを返すのと同じように、正規表現の末尾の最初のインスタンスで sed を停止したいと思います。例:
echo "This is a test some stuff I want string junk string end" | sed -n 's/.*\(.te.*ng\).*/\1/p'
returns: test some stuff I want string junk string
I want to return: test some stuff I want string
答え1
グレップアプローチ(必要ペクレサポート):
s="This is a test some stuff I want string junk string end"
grep -Po 'te.*?ng' <<< $s
代替パールアプローチ:
perl -ne 'print "$&\n" if /te.*?ng/' <<< $s
出力(両方のアプローチの場合):
test some stuff I want string
.*?
-?
ここは貪欲でない修飾子は、一致するように指示しますミニマルファッション
答え2
2 つの手順で実行します。まずプレフィックスを削除し (プレフィックスにターミネータが存在する場合)、次にプレフィックスの後のすべてを削除します。T
一致しない場合は、コマンドを使用して行をスキップします。
echo "This is a test some stuff I want string junk string end" |
sed -n 's/.*\(.te.*ng\)/\1/; T; s/\(ng\).*/\1/p'
または、一致しない行を最初に削除してから、都合のよいときに置換を実行します。
echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/!d; s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/'
または、一致する行に対してのみ置換と最終印刷を実行します。
echo "This is a test some stuff I want string junk string end" |
sed '/.*\(.te.*ng\)/ { s/.*\(.te.*ng\)/\1/; s/\(ng\).*/\1/p; }'
答え3
あなたの場合はカットコマンドを使用することをお勧めします
echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1
これにより、文字列が 3 つの部分 (最初の部分の前、2 番目の部分の後、および '文字列' の間) にカットされます。-d"" を使用すると、カッターとして使用するパターンを選択でき、-fNumber を使用すると、取得する部分を選択できます。問題: '文字列' が削除されます。解決策:
String=`echo "I am a useful and I am a string. Did I mention that I'm a string?" | cut -d "string" -f1`
String="$(String) string"
echo $String
削除された区切り文字「文字列」を、出力で定義された$String変数の末尾に追加します。
答え4
# 貪欲な一致を実行する方法: POSIX sed を使用して「test .*? string」
sed -e '
/test.*string/!d; # non-interesting line
/^test/s/string/&\
/; # append marker after the first substring "string"
/\n/{P;d;} # initial portion of pattern space is our result
s/test/\
&/;D; # remove portion before the substring "test"
' yourfile
別のPOSIX-リーこの方法は、パターン スペースの末尾から部分文字列 "string" を 1 つずつ取り除き、残りが 1 つだけになるまで (部分文字列 "test" の後) 続けます。次に、残った部分文字列 "test" を先頭に移動します。
sed -e '
:loop
s/\(test.*string\).*string.*/\1/
tloop
/^test/!s/test/\
&/;/\n/D
' yourfile