私はsedに対応したいと思います:。出力に対して追加の処理を実行したいとします。このステップは、おそらくより長いsed式を追加すると、より複雑になるタスクの最初の部分です。grep -Eo 'regex'
; s…
もっと明確に言えば、それぞれを分離できるようにしたいです。ひも 入力ストリームに提供された正規表現と一致します。概念を証明するために、これらの各文字列はコンテキストなしで別々の行に出力する必要があります(つまり、入力に周囲のテキストはありません)。したがって、複数の(重複しない)一致がある入力行は複数の出力行を生成し、一致がない入力行は出力を生成しないでください。
例:
正規表現: [a-zA-Z]{3}[0-9]{4}
(つまり、3文字の後に4つの数字が続きます)
入力する:
FGH1234 and CAS4057
MAX2345
出力:
FGH1234
CAS4057
MAX2345
答え1
長さゼロの正規表現の一致動作を修正するように更新されました。
sed 't match;s/REGEX/\n&\n/g;D;:match;/^\n/!P;s/\n//;D' file
一致をグローバルに置き換えます。次に、一致するすべての部分が印刷されるまで<newline><matched part><newline>
ループを作成して印刷します。空でない一致のみを印刷するには(GNUのように)、justの代わりにjustを使用してください。P;s/\n//;D
t match
/^\n/!P
P
grep -o
同様の方法を使用awk
できます。
regex='REGEX' awk 'BEGIN {FS="\n"}
gsub(ENVIRON["regex"], FS "&" FS) {for (i=2;i<NF;i+=2) if ($i!="") print $i}
' file
元の試行:.*
空の文字列に一致する正規表現(たとえば)が与えられた場合、これらのコマンドは正しく機能しません。空行は無限ループで印刷されます。
ワンコールでsed
:
sed '
t match
s/[[:alpha:]]\{3\}[[:digit:]]\{4\}/\
&\
/;D;:match
P;D' file
POSIX構文の使用:正規表現は、代替文字列でエスケープされた改行を使用し、分岐ラベルの後に改行を使用するデフォルトの正規表現sed
です。一部のバージョン(GNU sedなど)では、1行にすべてのスクリプトを許可できます。\
s///
;
sed
sed 't match;s/[[:alpha:]]\{3\}[[:digit:]]\{4\}/\n&\n/;D;:match;P;D' file
置換は、一致する部分の前後に改行文字を追加して、最初の一致を分離します。t match
スクリプトの先頭の条件分岐は、置換が成功した後にのみ続きます。:match
一致する部分が印刷される場所です。D
パターン空間から一致を含む行を削除し、残りを次のループの入力として使用して、より多くの一致を見つけることができるようにします。
答え2
これは次のようによく似ています。調整回答(ただし独立して開発されました)少し詳細な説明があるかもしれません。
GNU sedの使用:
sed -En 't dummy; : dummy; s/[a-zA-Z]{3}[0-9]{4}/&\n/; T; s/.*([a-zA-Z]{3}[0-9]{4}\n)/\1/; P; D'
説明する:
-E
拡張正規表現(ERE)を使用します。これがなければ、私たちは\{3\}
平和と言わなければなりません\{4\}
。n
何も自動的に印刷しないでください。印刷する内容だけを印刷してください。これは、grep
正規表現に一致する文字列を含まない入力行には何も印刷したくないので、これは望ましいです。t dummy; : dummy
次の("dummy
")ラベルに移動します。これは条件付きジャンプなので、発生したり発生したりしない可能性があります。しかし、ジャンプコマンドとラベルの間には何もないので問題はありません。これは、成功したタスクがあったことを確認するためにsedのメモリを消去することを除いて、何もしないようです。S代替コマンド。
s/[a-zA-Z]{3}[0-9]{4}/&\n/
OPの正規表現を探します。見つかった場合は、それ自体と改行文字に置き換えられます(つまり、改行文字が追加されます)。T
上記の代替コマンドが失敗した場合(パターンが見つかりません)、スクリプトの最後にジャンプして次の入力行を読みます。 文書なぜならT
、T label
-
入力ラインを最後に読み込んだ後、最後またはコマンドの後に成功した置換がない場合は、次に
s///
分岐します。t
T
label
;もしlabel
省略、スクリプトの最後に分岐します。これはGNU拡張です。これが私たちが
dummy
このラベルを使用する理由です。これT
このコマンドは前のコマンドのみを調べますs
。s/.*([a-zA-Z]{3}[0-9]{4}\n)/\1/
OPの前に任意の数の文字があることを見つける正規表現(.*
)の後に改行文字が続き、それを正規表現マッチングと改行文字に置き換えます(例:正規表現マッチングの前にあるすべてのテキストを削除)。一見するとこんな感じです。 最後ちょうど一致するので.*
欲を唱えなさい。しかし、最初の一致にのみ改行文字が付いてきたので、最初の項目を見つけましたs
。G地元の)。P
(水道人) 最初の改行文字の後にパターンバッファを印刷します。これは正規表現に一致する文字列です(grep -o
出力と同じ)。D
最初の改行文字でパターンバッファを削除し、スクリプトの先頭に移動します。
答え3
パイプでGNU sedを2回呼び出すと、grepと同じ出力が得られます。
sed -E 's/[a-zA-Z]{3}[0-9]{4}/\n&\n/g' input \
| sed -E '/^[a-zA-Z]{3}[0-9]{4}$/!d'
概念的に:
sed -E 's/REGEX/\n&\n/g' input \
| sed -E '/^REGEX$/!d'
最初の呼び出しは、周囲の改行文字から一致する正規表現を分離します。
2番目は、deletes
正規表現と一致しないすべての行を呼び出します。
実際に正規表現に正確に一致する行だけを印刷しますgrep -o
。
一部の拡張正規表現を使用して、前後の不要な部分を一致させて削除しようとすると、失敗を意味します。正規表現エンジンは、*
制限なしにあまりにも多くの項目(すべての項目のため)と一致するため、一致しますas much as possible
。 Lookaround Matchingを使用してPCREを構築すると、この問題を解決できますが、sed(現在のすべてのsed)はPCREを使用できません。
この回避策は単純で、既知の問題はありません(正規表現が「なし」と一致する場合は空白行がたくさん印刷される場合を除く)。
この使用量をsedの1行に減らすことは(驚くべきことに)かなり複雑になります。他の答えは、いくつかの特別なケースと複雑なsed構文を使用してこれを達成しようとします。
私たちは普遍的な解決策を見つけるために努力し続けます。
答え4
GNUの使用sed
$ sed -Ez ':a;s/([a-zA-Z]{3}[0-9]{4})[a-z ]+/\1\n/;ta' input_file
FGH1234
CAS4057
MAX2345
使用sed
$ sed -E 's/([a-zA-Z]{3}[0-9]{4}) [^A-Z]*/\1\
/' input_file
FGH1234
CAS4057
MAX2345