以下のような特定の行を含むテキストファイルがあります。
sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext
上記の行全体を置き換える必要があります。
This line is removed by the admin.
検索キーワードはTEXT_TO_BE_REPLACED
です
これにはシェルスクリプトを書く必要があります。 sed
を使ってこれを実現するにはどうすればよいですか
change コマンドを使用して行全体を置き換えることができ、-i
フラグを使用してその場で変更を加えることができます。たとえば、GNU sedを使用します。
sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
行全体を置き換えるには、前後にワイルドカード(.*
)を使用する必要があります。
sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'
受け入れられた答えは私にはいくつかの理由でうまくいきませんでした:
-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
上記の答え:
sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
置換文字列/行が変数ではない場合は正常に動作します。
問題はRedhat 5ではc
の後の\
が$
をエスケープすることです。二重の\\
も動作しませんでした(少なくともRedhat 5では)。
ヒットとトライアルの結果、置換文字列/行が単一行の場合、c
の後の\
が冗長であることがわかりました。だから私はc
の後に\
を使わず、変数を単一の置換行として使い、それは喜びでした。
コードは次のようになります。
sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo
一重引用符の代わりに二重引用符を使用することに注意してください。
設定ファイルの操作用
私は skensell回答に触発されたこの解決策を思い付きました
configLine [searchPattern] [replaceLine] [filePath]
そうなる:
関数:
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から来ています
これまでに提供されたすべての回答は、あなたが置き換えられるテキストについて何か理解していると仮定しています。置き換えられるテキストについて何も知っていないこと、および置き換えたくない同じ内容または類似の内容を含むファイル内に別の行がある可能性があることを前提にした回答を提供しています。さらに、置き換えられる行の行番号を知っていると仮定します。
次の例は、特定の行番号によるテキストの削除または変更を示しています。
# 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/'
私のメークファイルで私はこれを使用します:
@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md
PS: いけません -iが実際にファイル内のテキストを変更することを忘れないでください... "Revision"として定義したパターンが変わる場合は、置き換えるパターンも変更します。
出力例
John Doeによって書かれたAbcプロジェクト
改訂:1190
したがって、パターン「Revision:1190」を設定した場合、明らかに「Revision:」のみと定義したのと同じではありません。
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
'
それはうまくいきます
cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file
done
find_replaceファイルには2つの列があります。c1は一致するパターン、c2は置換です。sedループは、変数1のパターンの1つを含む各行を置換します。
上記と同じです。
sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'