私は電話番号のデータを保持するファイルと、いくつかの役に立たないものを持っています。電話番号を解析しようとしていますが、電話番号/回線が1つしかない場合は問題ありません。しかし、複数の数値がある場合、sedは最後の数値と一致し(最初のパターンにのみ一致する必要があるとどこにでもあると言われていても)、他の数値を取得できません。
私のdata.txt:
bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla
データを解析するときの最初のアイデアは、最初の電話番号の前にあるすべての「初期」「bla bla bla」を削除することでした(つまり、「NUM:」の最初の出現を検索します)。その後、すべてのものを削除します電話番号の後に、番号を取得します。その後、残りの文字列から次の出現を解析したいと思います。
だから今私がそれをsedしようとすると、私はいつも行の最後の番号を取得します:
>sed 's/.*NUM://' data.txt
08022222222 bla bla bla
>
主に私はSEDの私の理解の何が悪いのかを理解したいと思います。もちろん、より効率的な提案を歓迎します!私のsedコマンドは、 'NUM:'の前のすべてのものを ''(空)で置き換えませんか?なぜ常に最後に一致するのですか?
ありがとう!
これはあなたのために働くかもしれません:
echo "bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla" |
sed 's/NUM:/\n&/g;s/[^\n]*\n\(NUM:[0-9]*\)[^\n]*/\1 /g;s/.$//'
NUM:09011111111 NUM:08022222222
あなたが持っている問題は、.*
は貪欲です。つまり、最長一致に一致しますnot最初の一致。ユニークな文字(\n
sedはそれを行区切り文字として使用するため、対象の文字列(NUM:...
)そして、その固有の文字ではないすべてのものを削除します[^\n]*
の後に一意の文字\n
、文字列を扱いやすい断片に効果的に分割します。
今までにご存じのとおり、sed
正規表現は貪欲であり、私が知る限り、貪欲にすることはできません。
これまで実現されていなかった2つの代替策は、この種のマッチング/抽出に他のツールを使用することです。
Perl
は、-pe
パラメータを使用したsedのドロップイン置換として使用できます。 ?
non-greedy修飾子をサポートします:
$ Perl -pe 's/.*?NUM://' data.txt
09011111111 bla bla bla bla NUM:08022222222 bla bla bla
-o
オプションをGNU grepに使用すると、正規表現に一致するデータのビットのみを取得できます。
$ egrep -o 'NUM:[0-9]*' data.txt
NUM:09011111111
NUM:08022222222
数字がNUM:
に続く数字で定義されている場合:
sed -n -e 's/$/\n/' -e ':begin' \
-e 's/\(NUM:[0-9][0-9]*\)\(.*\)\n\(.*\)/\2\n\3 \1/' \
-e 'tbegin' -e 's/.*\n //' -e '/NUM/p'
これは何ですか:
\n
を行末に配置します。それはまた逆に行うことができ、最初に番号なしの行をドロップします:
sed -e '/NUM/!d' -e 's/$/\n/' -e ':begin' \
-e 's/\(NUM:[0-9][0-9]*\)\(.*\)\n\(.*\)/\2\n\3 \1/' \
-e 'tbegin' -e 's/.*\n //'
次のパターンを使用できます。
sed -r 's/^(.*NUM:)(.*NUM:.*)$/\2/'