私は次のデータを持っています。
<td><a href="data1">abc</a> ... <a href="data2">abc</a> ... <a href="data3">abc</a>
data
(上記の行は以下のコードのように参照されます)
data1
最初の間に必要なので、"
これを"
行います。
echo 'data' | sed 's/.*"\(.*\)".*/\1/'
しかし、それは私に返されます最後の文字列間"
と常につまり、この場合の代わりに"
私を返します。data3
data1
を得るために、data1
私は結局
echo 'data' | sed 's/.*"\(.*\)".*".*".*".*".*/\1/'
data1
そう多くの重複なしにこれをどのように得ることができますか?sed
答え1
正規.*
表現パターンは貪欲であり、可能な限り長い文字列と一致するため、一致する引用符が最後の引用符になります。
ここで区切り文字は単一の文字であるため、逆括弧セットを使用して引用符(たとえば)を除くすべての項目と一致させ、その一致を繰り返すことで引用符ではなく複数の[^"]
文字と一致させることができます。
$ echo '... "foo" ... "bar" ...' | sed 's/[^"]*"\([^"]*\)".*/\1/'
foo
もう1つの方法は、最初の参照より前のすべての項目を削除してから、(新しい)最初の参照から始まるすべての項目を削除することです。
$ echo '... "foo" ... "bar" ...' | sed 's/^[^"]*"//; s/".*$//'
foo
Perl正規表現では、疑問符を追加して指定子を貪欲にしないようにすることができ、*
できるだけ少ない文字/バイトのみを除くと何でも可能です。+
.*?
答え2
HTMLを解析するために単純な正規表現を使用することに関する古典的な警告であなたを退屈させません。私が言いたいのは、専用パーサーを使用する必要があるということです。つまり、ここでの問題は、sed
貪欲なマッチを使用することです。したがって、常に最長の文字列と一致します。これはあなたが.*
永遠に持続し、ライン全体と一致することを意味します。
(以下を参照)でこれを行うことができますが、sed
貪欲ではない一致を可能にするツールを使用する方が簡単です。
$ perl -pe 's/.*?"(.*?)".*/$1/' file
data1
non-greedyマッチングをサポートしていないため、sed
追加のトリックが必要です。最も簡単な方法は、「引用符なし」方法を使用することです。イカチュウの答え。代替案は次のとおりです。
$ rev file | sed 's/.*"\(.*\)".*/\1/' | rev
data1
これは元の方法を使用してファイル(rev
)を元に戻しました。これで、最初の項目が最後の項目であるために機能し、ファイルを再び戻します。
答え3
さまざまな方法で入力からdata1を抽出できます。
grep -oP '^[^"]*"\K[^"]*'
sed -ne '
/\n/!{y/"/\n/;D;}
P
'
perl -lne '/"([^"]*)"/ and print($1),last'
答え4
Perl正規表現の予測と予測を使用して、貪欲な検索を使用することもできます。
cat data | grep -Po '(?<=href=").*?(?=")' | head -n1