18

電話番号データを保持するファイルと、いくつかの役に立たないものがあります。番号を解析しようとしていますが、電話番号/回線が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:」の前のすべてのものを「」(空)に置き換えるとは言いませんか?常に最後のオカレンスに一致するのはなぜですか?

ありがとう!

4

5 に答える 5

25

これはあなたのために働くかもしれません:

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

あなたが抱えている問題は、が貪欲であること、つまり最初の一致ではなく.*最長の一致に一致することを理解することです。一意の文字 ( sed はそれを行区切り文字として使用するため、行に存在できません) を対象の文字列 ( ) の前に配置し、その一意の文字ではないすべてのものを削除し、その後に一意の文字が続くようにすることで、効果的に文字列を扱いやすい部分に分割します。\nNUM:...[^\n]*\n

于 2012-03-13T10:02:02.123 に答える
12

ご存じのとおり、sed正規表現は貪欲であり、私が知る限り、非貪欲にすることはできません。

これまで持ち出されていなかった 2 つの代替手段は、この種のマッチング/抽出に他のツールを使用することです。

perlパラメータを使用して sed のドロップイン置換として使用でき-peます。?非貪欲修飾子をサポートしています。

$ perl -pe 's/.*?NUM://' data.txt
09011111111 bla bla bla bla NUM:08022222222 bla bla bla

-oGNU grepのオプションを使用して、正規表現に一致するデータのビットのみを取得できます。

$ egrep -o 'NUM:[0-9]*' data.txt 
NUM:09011111111
NUM:08022222222
于 2012-03-13T11:35:20.030 に答える
3

数値が:に続く数字で定義されている場合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'

これは何をしますか:

  1. 行の最後にa\nを付けて、マーカーとして機能させます。
  2. マーカーの前にある番号を見つけて、行の最後(マーカーの後)に配置してください。
  3. 番号が見つかった場合は、上記の2に進んでください。
  4. マーカーの前に数字が残っていない場合は、数字の前のすべてを削除します。
  5. 番号が行にある場合は、それを印刷します(番号が見つからない場合を処理するため)。

逆に、最初に数字のない行を削除することもできます。

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 //'
于 2012-03-13T23:01:00.527 に答える
0

次のパターンを使用できます。

sed -r 's/^(.*NUM:)(.*NUM:.*)$/\2/'
于 2012-03-13T09:47:41.907 に答える