ファイル内の文字列 "xxx"と "yyy"の間のすべての文字を表示したいです(引用符は区切り文字の一部ではありません)。どうすればいいですか?たとえば、「Hello world xxxこれはyyyファイルです」と入力すると、「これはファイルです」と出力する必要があります。
答え1
答え2
これにより、目的のタスクが実行されます。
sed -e 's/xxx\(.*\)yyy/\1/'
これは、2つの区切り文字列が同じ行にあると仮定します。
答え3
この質問は、区切り文字が必ず同じ行にある必要がない場合にのみ意味があります。さまざまな方法で実行できますが(使用している場合でもsed
)、awk
より柔軟です。
#!/bin/sh ああ 開始{検索= 0; /xxx/ { if(!検索){ 発見= 1; $0 = substr($0, index($0, "xxx") + 3); } } /yyy/ { if(検索){ 発見= 2; $0 = substr($0, 0, index($0, "yyy") - 1); } } {もし(検索){ 印刷; if(検索==2) 発見= 0; } } '
行に最大1つの部分文字列がある場合は、次のデータを使用して簡単なテストを実行しました。
ここはxxx yyです 最初 第二年 xxx.x イヤ xxx#yyy
そして次の出力(スクリプトは「foo」、データは「foo.in」):
$猫 foo.in|./foo うん 最初 第二 。 X #
仕組みは、入力データがあり、$0
awkがパターン合計を順番に一致させてデータを印刷する最終段階に行く途中でさまざまな変更を行うことができることxxx
です。yyy
$0
しかし、この例は以下では機能しません。
xxxxHelloyyyxxxWorldyyy
最初の一致のみを確認するためです。 Perlスクリプトは、awkの例で使用したように、インデックス/サブストリングの代わりにグリディマッチングを使用するため、異なる結果が得られます。もちろん、Perlはスクリプトを使用して同じことを行うこともできます。
Awk(Perlなど)は自由形式なので、コマンドは次のように表現できます。
awk 'BEGIN{found=0;}/xxx/{if(!found){found=1;$0=substr($0,index($0, "xxx")+3);}}/yyy/{if(found){found=2;$0=substr($0,0,index($0,"yyy")-1);}}{ if(found){print;if(found==2)found=0;}}'
しかし、これは例を除いてほとんど行われません。同様に、sed
スクリプト(行ベース)は、いくつかの制限を除いて1行にまとめることができます。同様に、複雑なスクリプトはsed
このように処理されることはほとんどありません。代わりに、実際のプログラムとして扱われます(参照:はい)。
追加資料:
答え4
xxx
同じ行にあるときとない場合でもyyy
動作するソリューション:
cat /tmp/xxx-to-yyy| perl -ne '(/xxx/../yyy/) && print' | perl -pe 's/.*(xxx.*)/$1/' | perl -pe 's/(.*yyy).*/$1/'
あまりきれいではありません...
コマンドラインからスクリプトを提供することに-e
切り替えました。入力行を繰り返し作成し、perl
スクリプトの後に印刷しますが、そうではありません。したがって、デフォルトでは、これは3つのPerlループを介してファイルを送信します。-n
-p
-p
-n
..
左の条件が true を返す前に false を返し、右の条件が true を返した後に false を返す範囲演算子です。したがって、最初のループはファイルを2つの文字列(両方を含む)の間の行に切り捨てます。最後の 2 つの perl コマンドは、xxx
前と右の条件のテキストを削除します。後yyy
。