Sedを使用して文字列を含む行全体を置き換える


319

私は次のような特定の行を持つテキストファイルを持っています

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

上記の行全体を次のように置き換える必要があります

This line is removed by the admin.

検索キーワードは TEXT_TO_BE_REPLACED

このためのシェルスクリプトを記述する必要があります。どうすればこれを使用してこれを達成できsedますか?


@Scharron私はsed -rne 's /(TEXT_TO_BE_REPLACED)\ s + \ w + / \ 1 yyy / xxx'を試しましたが、yyyが存在する場合、それは文字列内のyyyをxxxに置き換えるだけです。私の場合、テキストは修正されていません... TEXT_TO_BE_REPLACEDしかありません。
Rahul

これは有効なsed式ではありません。sedでよろしいですか?優れた正規表現を持つプログラミング言語であれば、代わりに置き換えることができます(サブ関数を検索)。それは自分でsedを理解するよりも簡単でしょう
Scharron

@Scharronまあ、それはシェルスクリプトで行われるので、sedが私の最善の策だと思います。
Rahul、2012

回答:


483

changeコマンドを使用して行全体を置き換え、-iフラグを使用して変更をインプレースで行うことができます。たとえば、GNU sedを使用します。

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

4
c \の前にスペースが必要であることに注意してください。これを追加するために編集しました。
Marcus Downing

27
@MarcusDowning GNU sedはスペースを必要としませ。最初に投稿されたとおりに正常に動作します。特定のsedにスペースが必要な場合は、どのsedに互換性がないかを必ず記録し、必要な呼び出しをコメントとして追加してください。ただし、承認された回答の作業コードを変更しないでください。
トッドA.ジェイコブス

7
「This ...」というテキストの代わりに変数を使用するにはどうすればよいですか?$ variableに置き換えると、内容ではなく変数名が出力されます。
スティーブン

18
c\ 変数が直接続く場合に問題があります。…c\$VAR…円記号はドルをエスケープします。この場合、私は(bashの/ Ubuntuの15.10でSEDが)書かなければならなかった…c\\$VAR…
ヤン

6
Macでの使用:sed -i '' '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo; (最初のパラメーターが空白の場合はファイル内で編集され、それ以外の場合はバックアップが作成されます)
AndreDurao 2018

152

.*行全体を置き換えるには、前後にwildards()を使用する必要があります。

sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'

ありがとう、私の作業が始まりました:sed 's /.* <expression>。* / <expression> SE_LABEL = ABC <expression> / g' MYR2.xml> test.txt
Nasri Najib

9
:これは、次のように私は-iおよび-eフラグを使用していますことを除いてはMac OS Xヨセミテに取り組んでいるsed -i -e "s/.*search_string.*/Replacement_line/' file_being_searched.txt
ケントブル

1
@KentJohnsonコマンドの引用符が一致していないと思います。
HashHazard

@MBarnett正解です。2つの二重引用符が必要です。
ケントブル

2
完全な情報のためだけに。それを-i
インプレースに

20

受け入れられた答えはいくつかの理由で私にとってうまくいきませんでした:

  • 私のバージョンのsedは-i、長さがゼロの拡張子が好きではありません
  • c\コマンドの構文が奇妙で、動作させることができませんでした
  • エスケープされていないスラッシュが原因で問題が発生していることに気づかなかった

だからここに私が思いついた解決策があり、私はほとんどの場合にうまくいくはずだと思います:

function escape_slashes {
    sed 's/\//\\\//g' 
}

function change_line {
    local OLD_LINE_PATTERN=$1; shift
    local NEW_LINE=$1; shift
    local FILE=$1

    local NEW=$(echo "${NEW_LINE}" | escape_slashes)
    sed -i .bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
    mv "${FILE}.bak" /tmp/
}

したがって、問題を修正するためのサンプルの使用法は次のとおりです。

change_line "TEXT_TO_BE_REPLACED" "This line is removed by the admin." yourFile

18

上記の答え:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

置換文字列/行が変数でない場合は正常に動作します。

問題は、Redhat 5 \cエスケープの後$です。doubleも機能\\しませんでした(少なくともRedhat 5では)。

ヒットとトライアルの結果、置換\後のc文字列/行が1行だけの場合、後が冗長であることを発見しました。なので、の\後は使用せずc、変数を1つの置換行として使用しました。

コードは次のようになります。

sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo

一重引用符の代わりに二重引用符を使用していることに注意してください。


次のように単一引用符を引き続き使用できます:sed -i '/ TEXT_TO_BE_REPLACED / c' "$ VARIABLE" '' / tmp / foo
Alistair McIntyre

4

これまでに提供されたすべての回答は、OPが要求するものであるため、置き換えられるテキストについて理解できるものを知っていると想定しています。置き換えられるテキストについて何も知らないと想定し、置き換えたくない同じまたは類似のコンテンツを含む別の行がファイルに含まれている可能性があるという答えを提供します。さらに、置き換えられる行の行番号がわかっていると仮定します。

次の例は、特定の行番号によるテキストの削除または変更を示しています。

# replace line 17 with some replacement text and make changes in file (-i switch)
# the "-i" switch indicates that we want to change the file. Leave it out if you'd
#   just like to see the potential changes output to the terminal window.
# "17s" indicates that we're searching line 17
# ".*" indicates that we want to change the text of the entire line
# "REPLACEMENT-TEXT" is the new text to put on that line
# "PATH-TO-FILE" tells us what file to operate on
sed -i '17s/.*/REPLACEMENT-TEXT/' PATH-TO-FILE

# replace specific text on line 3
sed -i '3s/TEXT-TO-REPLACE/REPLACEMENT-TEXT/'

3

設定ファイルの操作用

私はスケンセルの回答に触発されたこのソリューションを思いつきました

configLine [searchPattern] [replaceLine] [filePath]

そうなる:

  • 存在しない場合はファイルを作成します
  • searchPatternが一致した行全体(すべての行)を置き換える
  • パターンが見つからなかった場合は、ファイルの最後にreplaceLineを追加します

関数:

function configLine {
  local OLD_LINE_PATTERN=$1; shift
  local NEW_LINE=$1; shift
  local FILE=$1
  local NEW=$(echo "${NEW_LINE}" | sed 's/\//\\\//g')
  touch "${FILE}"
  sed -i '/'"${OLD_LINE_PATTERN}"'/{s/.*/'"${NEW}"'/;h};${x;/./{x;q100};x}' "${FILE}"
  if [[ $? -ne 100 ]] && [[ ${NEW_LINE} != '' ]]
  then
    echo "${NEW_LINE}" >> "${FILE}"
  fi
}

クレイジーな終了ステータスの魔法はhttps://stackoverflow.com/a/12145797/1262663から来ています


2
bash-4.1$ new_db_host="DB_HOSTNAME=good replaced with 122.334.567.90"
bash-4.1$ 
bash-4.1$ sed -i "/DB_HOST/c $new_db_host" test4sed
vim test4sed
'
'
'
DB_HOSTNAME=good replaced with 122.334.567.90
'

それはうまくいきます


1

私のメイクファイルでは、これを使用します:

@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md

PSは:しないでくださいあなたが「改訂」として定義されたパターンが変化する場合、実際に-i変更ファイル内のテキストは...そう、あなたも交換するパターンを変更することを忘れています。

出力例:

John Doeによって書かれたABCプロジェクト

リビジョン:1190

したがって、「Revision:1190」というパターンを設定した場合、「Revision:」のみとして定義したパターンとは明らかに異なります...


1
cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file    
done 

find_replaceファイルには2つの列が含まれ、c1は一致するパターン、c2は置換、sedループは変数1のパターンの1つを含む各行を置き換えます


いいえ、これはいくつかの点で間違っています。実行するsedすべての置換を含むスクリプトファイルを使用して1回実行します。sed -i同じファイルで繰り返し実行することは恐ろしいアンチパターンです。
tripleee 2018

0

上記と同様です。

sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'

3
そのように変更FOO=TEXT_TO_BE_REPLACEDするFOO=This line ...と、仕様を満たしません。
Jens 2013年

はい。私たちの要件は、行全体を「この行は管理者によって削除されました」で置き換えることです。キーパターン「TEXT_TO_BE_REPLACED」が見つかった場合。上記のコマンドは満足のいくものです。私の理解が間違っている場合は私を修正してください。@ Jens
Annapureddy Hari

@AnnapureddyHariこの回答は、検索文字列の前後のテキストにA-Za-z0-9以外のものが含まれている場合は機能しません。イェンスが指摘したように、等号があると失敗します。"FOO ="部分は残ります。行全体を置き換えていません。このコードは、ファイルに何が含まれるかについて近視眼的です。ワイルドカードを意味する場合は、トールの答えが示すように、ワイルドカードを使用する必要があります。
msouth 2016年

0

以下のコマンドは私のために働いています。変数を使用している

sed -i "/\<$E\>/c $D" "$B"

しかし、私の新しい要件は、置換するときにコメントを付けた(#で始まる)行をスキップすることです。完全な行を置き換えるので、コメント付きの行も置き換えられ、プロパティが重複することになります。誰かがこれに対する解決策を持っているなら、私に知らせてください。
Ritesh Borkar

-1

私は正規表現を使用してファイルからデータを抽出することがよくあります。これを使用して、リテラルの引用符\"//何も置き換えません:-)

cat file.csv | egrep '^\"([0-9]{1,3}\.[0-9]{1,3}\.)' | sed  s/\"//g  | cut -d, -f1 > list.txt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.