行内のパターンの前に改行を挿入するにはどうすればよいですか?
たとえば、これにより正規表現パターンの後ろに改行が挿入されます。
sed 's/regex/&\n/g'
どうすれば同じことをパターンの前で行うことができますか?
このサンプル入力ファイルを考えると、一致するパターンは電話番号です。
some text (012)345-6789
になるはずです
some text
(012)345-6789
これは、LinuxおよびOS Xで動作し、テストされていますbash
。zsh
sed 's/regexp/\'$'\n/g'
一般に、$
一重引用符で囲まれた文字列リテラルの後には、bash
Cスタイルのバックスラッシュ置換が実行されます。たとえば$'\t'
、リテラルタブに変換されます。さらに、sedは、改行リテラルをバックスラッシュでエスケープすることを望んでいます。したがって、\
before$
です。そして最後に、シェルによって解釈されるようにドル記号自体を引用するべきではありません。したがって、の前に引用符を閉じてから、$
もう一度開きます。
編集:@ mklement0によるコメントで示唆されているように、これも同様に機能します。
sed $'s/regexp/\\\n/g'
ここで何が起こるかというと、sedコマンド全体がCスタイルの文字列になりました。つまり、新しい行リテラルを別のバックスラッシュでエスケープする前に、sedのバックスラッシュを配置する必要があります。読みやすくなりますが、この場合、シェル文字列の置換を行うことはできません(再び醜くすることなく)。
他の回答のいくつかは、私のバージョンの sed では機能しませんでした。との位置を切り替える&
と\n
うまくいきました。
sed 's/regexp/\n&/g'
編集: をインストールしない限り、これは OS X では動作しないようですgnu-sed
。
sedでは、出力ストリームに改行を簡単に追加することはできません。継続線を使用する必要がありますが、これは厄介ですが、機能します。
$ sed 's/regexp/\
&/'
例:
$ echo foo | sed 's/.*/\
&/'
foo
詳細はこちらをご覧ください。少し厄介なものが必要な場合はperl -pe
、sedの代わりにマッチグループで使用してみてください。
$ echo foo | perl -pe 's/(.*)/\n$1/'
foo
$1
正規表現で最初に一致したグループを指します。グループは括弧で囲まれています。
私のMacでは、以下は改行の代わりに単一の「n」を挿入します:
sed 's/regexp/\n&/g'
これは改行に置き換えられます:
sed "s/regexp/\\`echo -e '\n\r'`/g"
echo one,two,three | sed 's/,/\
/g'
sed と同じように perl ワンライナーを使用でき、完全なperl 正規表現サポート (sed よりもはるかに強力) を利用できます。また、*nix プラットフォーム間での違いはほとんどありません。通常、perl は perl です。そのため、特定のシステムのバージョンの sed を希望どおりに動作させる方法について心配する必要はありません。
この場合、次のことができます。
perl -pe 's/(regex)/\n$1/'
-pe
sed の通常の操作モードと同様に、perl を「実行と出力」ループに入れます。
'
シェルが干渉しないように、他のすべてを引用します
()
正規表現を囲むのはグループ化演算子です。 $1
置換の右側には、これらの括弧内で一致したものがすべて出力されます。
最後に\n
、改行です。
グループ化演算子として括弧を使用しているかどうかに関係なく、一致させようとしているすべての括弧をエスケープする必要があります。したがって、上記のパターンに一致する正規表現は次のようになります
\(\d\d\d\)\d\d\d-\d\d\d\d
\(
or\)
は、リテラルの括弧に\d
一致し、数字に一致します。
より良い:
\(\d{3}\)\d{3}-\d{4}
中括弧内の数字が何をしているのか理解できると思います。
さらに、正規表現には / 以外の区切り文字を使用できます。したがって、一致する必要がある場合は、エスケープする必要はありません。以下のいずれかは、私の回答の冒頭にある正規表現と同等です。理論的には、標準の / を 任意の文字に置き換えることができます 。
perl -pe 's#(regex)#\n$1#'
perl -pe 's{(regex)}{\n$1}'
いくつかの最終的な考え。
using-ne
の代わりに-pe
同様に機能しますが、最後に自動的に出力されません。自分で印刷したい場合に便利です。たとえば、grep-alike は次のとおりです (m/foobar/
は正規表現の一致です)。
perl -ne 'if (m/foobar/) {print}'
改行を処理するのが面倒で、魔法のように処理したい場合は、-l
. ただし、改行を扱っていたOPには役に立ちません。
おまけのヒント - pcre パッケージがインストールされている場合は、pcregrep
perl と完全に互換性のある正規表現を使用する が付属しています。
この場合、sed は使用しません。私はtrを使用しています。
cat Somefile |tr ',' '\012'
これはカンマを取り、それをキャリッジ リターンに置き換えます。
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'
()
サポート付きの El Captitan で正常に動作しました
sed
うーん、エスケープされた改行は、 (私は GNU sed 4.2.1 を持っています)の最近のバージョンで動作するようです。
dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar
Linux で出力ストリームに改行を挿入するには、次を使用しました。
sed -i "s/def/abc\\\ndef/" file1
どこfile1
にいた:
def
sed インプレース置換前、および:
abc
def
sedインプレース交換後。の使用にご注意ください\\\n
。パターンに が含まれている場合は、"
を使用してエスケープし\"
ます。
sedでは、パターン内のグループを「\ 1」、「\ 2」などで参照できます。したがって、探しているパターンが「PATTERN」であり、その前に「BEFORE」を挿入する場合、あなたは使うことができます、逃げることはありません
sed 's/(PATTERN)/BEFORE\1/g'
すなわち
sed 's/\(PATTERN\)/BEFORE\1/g'
-v
パターンを提供するためにawk を使用してこれを行うこともできます。
awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
これは、行に特定のパターンが含まれているかどうかを確認します。その場合、その先頭に改行を追加します。
基本的な例を参照してください。
$ cat file
hello
this is some pattern and we are going ahead
bye!
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
hello
this is some
pattern and we are going ahead
bye!
行内のすべてのパターンに影響することに注意してください。
$ cat file
this pattern is some pattern and we are going ahead
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' d
this
pattern is some
pattern and we are going ahead
sed -e 's/regexp/\0\n/g'
\0はヌルであるため、式はヌル (何もない) に置き換えられ、その後...
\nは改行です
Unix のいくつかのフレーバーでは動作しませんが、それが問題の解決策だと思います。
echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow
これは私にとってMACで機能します
sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt
完璧なのかどん...
この質問に対するすべての回答を読んだ後でも、次のサンプル スクリプトの正しい構文を取得するために何度も試行錯誤しました。
#!/bin/bash
# script: add_domain
# using fixed values instead of command line parameters $1, $2
# to show typical variable values in this example
ipaddr="127.0.0.1"
domain="example.com"
# no need to escape $ipaddr and $domain values if we use separate quotes.
sudo sed -i '$a \\n'"$ipaddr www.$domain $domain" /etc/hosts
このスクリプトは、単一のコマンド\n
を使用して、改行とそれに続く別のテキスト行をファイルの末尾に追加します。sed