文字の最初のインスタンスとすべての後続の文字を置き換えるようにsedコマンドを改善しますか?

文字の最初のインスタンスとすべての後続の文字を置き換えるようにsedコマンドを改善しますか?

入力する:

<e1 name="file1" id="id1" anotherId="id2">

希望の出力:

file1

次のように必要なものを入手できます。

echo '<e1 name="file1" id="id1" anotherId="id2">' | sed 's/\(.*name="\)\(.*\)\(".*\)/\2/' | sed 's/".*//'

出力:file1

可能であれば、コマンドセットを改善し、sedの最後のパイプを削除したいと思います。 sedの最後のパイプを削除すると、目的の結果が得られません。

echo '<e1 name="file1" id="id1" anotherId="id2">' | sed 's/\(.*name="\)\(.*\)\(".*\)/\2/'

出力:

file1" id="id1" anotherId="id2

ご覧のとおり、sedはfile1の後の最初の引用符ではなく、最後の引用符を選択しました。

誰でもこのコマンドを改善するのに役立ちますか?

答え1

echo '<e1 name="file1" id="id1" anotherId="id2">' |
  sed -n 's/.*name="\([^"]*\)".*/\1/p'

またはGNUを使用する(grepPCREサポートで構築されている場合):

echo '<e1 name="file1" id="id1" anotherId="id2">' |
  grep -Po 'name="\K[^"]*'

答え2

sed

このバージョンでは、少し簡単にすることができます。

$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
   sed 's/.*name="\(.*\)" id.*/\1/'

すべてを括弧で囲む必要はありません。後で削除できるように興味のあるアイテムを保存してください。

grep

grepPerlの正規表現エンジン(PCRE)機能を使用することもできます。

$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
   grep -Po '(?<=name=")(\w+)(?=")'

これは、PCREの将来指向的および過去指向的な機能を利用します。この表記法は、次の文字シーケンスを探します。"name=" 今後私たちは何を探していますか?このビットはそれをしています:

(?<=name=")

それから私たちが実際に探している一連の単語文字を見つけます。

(\w+)

前を見下ろす最後のポイントは次のとおりです。

(?=")

"引用符()を探しています。後ろに私たちは何を探していますか?

アッ

$ echo '<e1 name="file1" id="id1" anotherId="id2">' | \
   awk '{gsub("\"","");split($2,a,"="); print a[2]}'

このバリアントは、グローバル置換のために二重引用符( `` `` ``)を文字列にします。

gsub("\"","")

残りの文字列は次のようになります。

<e1 name=file1 id=id1 anotherId=id2>

したがって、awk一般的なように分割すると、2番目の列が私たちが興味のある部分になります。それはなり$2ますawk。したがって、その変数を取得して等号(=)に分割できます。

split($2,a,"=");

これにより$2結果が分割され、配列に保存されますa。その後、等号の右側にあるすべての項目である配列の2番目の要素を印刷できます$2

file1

関連情報