パターンの前に改行を挿入するにはどうすればよいですか?


138

行内のパターンの前に改行を挿入するにはどうすればよいですか?

たとえば、これは正規表現パターンの後ろに改行を挿入します。

sed 's/regex/&\n/g'

どうすればパターンので同じことができますか?

このサンプル入力ファイルの場合、照合するパターンは電話番号です。

some text (012)345-6789

なるはず

some text
(012)345-6789


1
@NilsvonBarth、なぜ簡単な質問が悪い質問なのですか?
Josh、

回答:


177

この作品にbashし、zshLinuxとOS X上でテストされ、:

sed 's/regexp/\'$'\n/g'

一般に、forの$後に単一引用符で囲まれた文字列リテラルが続くと、bashCスタイルのバックスラッシュ置換$'\t'が実行されます。たとえば、リテラルタブに変換されます。さらに、sedは、改行リテラルがバックスラッシュでエスケープされることを望んでいるため、\before $です。最後に、ドル記号自体は引用符で囲まないでください。シェルで解釈されるため、引用符を閉じる前に閉じ、$再度開きます。

編集:@ mklement0のコメントで提案されているように、これも機能します。

sed $'s/regexp/\\\n/g'

ここで何が起こるか:sedコマンド全体がCスタイルの文字列になりました。つまり、改行リテラルが別のバックスラッシュでエスケープされる前に、sedがバックスラッシュを配置する必要があります。より読みやすいですが、この場合、シェル文字列の置換を(再び醜くすることなく)行うことはできません。


7
これにより、OSXで「代替パターン内のエスケープされていない改行」が表示されます。
マットギブソン

「エスケープされていない改行」は、置換パターン内にバックスラッシュのない実際の改行がある場合にのみ与えられるため、非常に奇妙な@マットギブソン。上記の私のコードは、実際には、zsh、kshなどの他のシェルでも動作します。
mojuba 2013

3
@マットギブソン...または、私のコードで '$'の前のバックスラッシュを忘れた場合\ n
mojuba 2013

7
書かれているように、これらの式は、要求に応じて既存の行の途中に改行を挿入するのではなく、正規表現を改行で完全に置き換えます。これは、この回答の修正された形式を使用して、2つの一致したパターンの間に改行を挿入する方法ですsed '\(first match\)\(second match\)/\1\'$'\n''\2/g'。\ nの後の2つの一重引用符に注意してください。最初$の行は" "セクションを閉じて、行の残りの部分が影響を受けないようにします。これらの引用符がなければ、\ 2は無視されました。
David Ravetti 14

12
別のオプションは、単一の ANSI C引用文字列:を使用することですsed $'s/regexp/\\\n/g'。これにより、読みやすさが向上します。唯一の注意点は、すべてのリテラル文字を2倍にする必要があることです\
mklement0 2015年

43

他の回答の一部は、私のバージョンのsedでは機能しませんでした。位置を切り替える&\n仕事をしました。

sed 's/regexp/\n&/g' 

編集:をインストールしない限り、これはOS Xでは機能しないようですgnu-sed


9
これがsedのすべてのバージョンで機能するかどうかはわかりません。私のMacでこれを試してみたところ、\ nは「n」と出力されました
Todd Gamblin

3
あなたの答えを読む前に、私の仕事でMacで15分過ごしました。アップルに行こう!
Rick77

1
homebrewを使用している場合:brew install gnu-sed続いてgsed 's/regexp/\n&/g'
aaaaaa

1
...後に続くecho 'alias sed=gsed' >> ~/.bashrc
Proximo 2018

36

sedでは、出力ストリームに改行を簡単に追加することはできません。面倒な継続行を使用する必要がありますが、機能します。

$ sed 's/regexp/\
&/'

例:

$ echo foo | sed 's/.*/\
&/'

foo

詳細はこちらをご覧ください。少し厄介なものが必要な場合はperl -pe、sedの代わりに一致グループを使用してみてください。

$ echo foo | perl -pe 's/(.*)/\n$1/'

foo

$1 正規表現で最初に一致したグループを指します。グループは括弧内にあります。


なぜ改行を追加できないと言うのですか?sed 's / regexp /&\ n / g'を実行するだけです
Andres

2
これは、Macで改行を挿入するためにできる
最もハッキングさ

Perlバージョンは、インプレース編集を行うように変更できますperl -pi -e 's/(.*)/\n$1/' foo
代名詞

2
@Andres:(主に)OS Xにも付属するBSDバージョンなどのPOSIX機能のみのSed実装は、s関数呼び出しの置換部分で制御文字エスケープシーケンスをサポートしていません(GNU Sed実装とは異なります)。 。上記の回答は両方の実装で機能します。すべての違いの概要については、こちらを参照してください
mklement0 2015年

29

私のMacでは、以下は改行の代わりに単一の「n」を挿入します。

sed 's/regexp/\n&/g'

これは改行で置き換えられます:

sed "s/regexp/\\`echo -e '\n\r'`/g"

インライン編集sed -i '' -e ...を行っていて、^MキャレットM(ctrl + m)がファイルに書き込まれるという問題がありました。私は同じパラメータを持つperlを使用してしまいました。
スティーブタウバー2013年

2
2番目のコードが特別な改行コードLF CR(MS-DOS CR LFの逆)を挿入するという事実に注意してください!UnixライクなOSとMac OS XはどちらもLF(\n)だけを使用します。
pabouk 2013

私のsed表現の他の何かが非常に不幸を引き起こしていたため(echo...および改行なしで正常に動作しているにもかかわらず)、vimでこれを実行しただけです。
Ahmed Fasih 2014年

1
または単に:sed "s/regexp/`echo`/g"-これはLF-CRではなく単一のLFを生成します
mojuba '29

2
@mojuba:いいえ:コマンドの置換は常にすべての末尾の改行を削除`echo`するため、空の文字列なります。コマンド置換を使用して単一の改行を直接挿入する方法はありません(挿入\n\r-つまり、追加のCR-はひどい考えです)。
mklement0 2015年

15
echo one,two,three | sed 's/,/\
/g'

1
+1は完璧に機能し、かなり前向きで覚えやすい
gMale 2013年

2
この答えは実際にはbashソリューションではなくsedソリューションです。のような構成を使用するものはすべて、シェルを使用して改行を生成します。このようなソリューションは、移植できない場合があります。これは。もちろん、それは2009年からtgamblinの答えでも、第二の例の重複だ$'\n'
ghoti

10

この場合、sedは使用しません。私はtrを使用します。

cat Somefile |tr ',' '\012' 

これはコンマを取り、キャリッジリターンで置き換えます。


1
これも機能することがわかりました:cat Somefile | tr ',' '\n'YMMV
LS

9

perlの正規表現を完全にサポートするという利点(sedで得られるものよりもはるかに強力です)を利用して、sedと同じようにperlワンライナーを使用できます。また、* nixプラットフォーム間での違いはほとんどありません-perlは通常perlです。そのため、特定のシステムのバージョンのsedを希望どおりに動作させる方法について心配する必要がなくなります。

この場合、次のことができます

perl -pe 's/(regex)/\n$1/'

-pe perlをsedの通常の操作モードと同じように、「実行して印刷」ループに入れます。

' シェルが干渉しないように他のすべてを引用します

()正規表現を囲むのはグループ化演算子です。 $1置換の右側には、これらの括弧内で一致したものがすべて出力されます。

最後に\n、改行です。

括弧をグループ化演算子として使用しているかどうかに関係なく、一致させようとする括弧はエスケープする必要があります。したがって、上記のリストに一致する正規表現は次のようになります

\(\d\d\d\)\d\d\d-\d\d\d\d

\(または\)、リテラルの括弧と\d一致し、数字と一致します。

より良い:

\(\d{3}\)\d{3}-\d{4}

中括弧内の数字が何をしているのか理解できると思います。

さらに、/以外の区切り文字を正規表現に使用できます。したがって、一致する必要がある場合は、エスケープする必要はありません。以下のどちらも、私の回答の冒頭の正規表現に相当します。理論的には、標準の/の代わりに任意の文字を使用できます 。

perl -pe 's#(regex)#\n$1#'
perl -pe 's{(regex)}{\n$1}'

いくつかの最終的な考え。

-ne代わりにを使用して-peも同様に動作しますが、最後に自動的に印刷されません。自分で印刷したい場合に便利です。たとえば、これはgrepに似ています(m/foobar/正規表現の一致です)。

perl -ne 'if (m/foobar/) {print}'

改行の扱いが面倒で、魔法のように処理させたい場合は、を追加し-lます。ただし、改行を処理していたOPには役立ちません。

ボーナスのヒント-pcreパッケージがインストールされている場合は、pcregrep完全なperl互換の正規表現を使用するが付属しています。


4

うーん、エスケープされた改行は、より最近のバージョンsed(私はGNU sed 4.2.1を持っています)で機能するようです、

dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar

1
前述のように、これはGNU sedのさまざまなバージョンで機能しますが、macOSに含まれているsedでは機能しません。
LS

4
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'

El Captitanの()サポートで問題なく動作した


これは非常にうまくいき、自分自身の目的に特化するためにテストおよび推定する完全なコマンドを与えることさえできます。良くやった!
jxramos

3

Linuxで出力ストリームに改行を挿入するには、以下を使用しました。

sed -i "s/def/abc\\\ndef/" file1

どこにfile1あった:

def

sedインプレース置換の前、および:

abc
def

sedインプレース置換後。の使用にご注意ください\\\n。パターンに"内部がある場合は、を使用してエスケープし\"ます。


私にとって、上記のコードは機能しません。シェルからパラメーターを取得するため、LFの代わりにsed挿入します。---このコードは機能します。--- 、(CentOSリリース6.4 / Ubuntu 12.04.3)。\n\\nsed -i "s/def/abc\ndef/" file1GNU sed version 4.2.1GNU bash, version 4.1.2(1) / 4.2.25(1)
pabouk 2013

2

sedでは、パターン内のグループを「\ 1」、「\ 2」、...で参照できます。したがって、探しているパターンが「PATTERN」であり、その前に「BEFORE」を挿入したい場合、使用できる、エスケープしない

sed 's/(PATTERN)/BEFORE\1/g'

すなわち

  sed 's/\(PATTERN\)/BEFORE\1/g'

ちょうどした:testfile contents = "ABC ABC ABC"。"sed 's / \(ABC \)/ \ n \ 1 / g' testfileを実行し、改行を取得しました。エスケープを試して、パターンに一度に1つずつ追加してみてください。たとえば、パターン、次にグループマッチングをチェックし、改行チェックを追加します
スティーブB.

私はちょうどそれを試してみて、「nABC nABC nABC」を取得しました。他のバージョンのsedを使用していますか?
Todd Gamblin

シェルエスケープはおそらくtgamblinの試みの邪魔になっています。Steve Bが行ったように、sed引数全体を単一引用符で囲むことで、これを修正できます。ただし、sedの異なるバージョンが改行の\ nを理解していない可能性があります。
Dan Pritts、2014年

2

これをawkで行うこともできます。これを使用-vしてパターンを提供します。

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

1
これで1は何をしますか?
whatahitson

1
@whatahitson 1は、Awk ではの省略形として使用され{print $0}ます。その理由は、Trueと評価されるすべての条件が、Awkのデフォルトアクションをトリガーし、現在のレコードを印刷することです。
fedorqui 'SO stop harming'

1

これはMACで機能します

sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt

その完璧なものかどうか...


1

この質問に対するすべての回答を読んだ後も、次のスクリプト例の正しい構文を取得するために多くの試みを行いました。

#!/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コマンドを使用して、改行の後に別のテキスト行をファイルの最後に追加します。


1
sed -e 's/regexp/\0\n/g'

\ 0はnullであるため、式はnull(何もない)に置き換えられます...
\ nは新しい行です

Unixのいくつかのフレーバーでは機能しませんが、それが問題の解決策だと思います。

echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow

0

Red Hatのviでは、\ r文字だけを使用して改行を挿入できました。これは「sed」の代わりに「ex」を内部で実行すると思いますが、それは似ています。viは、コードパッチなどの一括編集を行う別の方法になる場合があります。例えば。中括弧の後に改行を要求するifステートメントで検索語を囲んでいます。

:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/

配置を整えるためにいくつかのタブを挿入することにも注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.