交換する前にsedに確認を求める方法はありますか?vim内でreplaceを使用する場合の「c」に似たもの。
sedはこれをまったく行いますか?
交換する前にsedに確認を求める方法はありますか?vim内でreplaceを使用する場合の「c」に似たもの。
sedはこれをまったく行いますか?
回答:
sed
非対話型のストリームエディタであるため、これを使用することはおそらく不可能です。sed
スクリプトでラップするには、あまりにも多くの思考が必要です。単にそれを行う方が簡単ですvim
:
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' file.in
以下のコメントで言及されているため、現在のディレクトリ内の特定のファイル名グロビングパターンに一致する複数のファイルでこれを使用する方法を次に示します。
for fname in file*.txt; do
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
または、置換を実行する前に、指定されたパターンに一致する行が最初にファイルに含まれていることを最初に確認したい場合は、
for fname in file*.txt; do
grep -q 'PATTERN' "$fname" &&
vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' "$fname"
done
上記の2つのシェルループfind
は、同じことを行うコマンドに変更されていますが、top-dir
ディレクトリ内またはディレクトリの下の特定の名前を持つすべてのファイルに対して、
find top-dir -type f -name 'file*.txt' \
-exec vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' {} \;
find top-dir -type f -name 'file*.txt' \
-exec grep -q 'PATTERN' {} \; \
-exec vim -c '%s/PATTERN/REPLACEMENT/gc' -c 'wq' {} \;
または、元のシェルループを使用し、find
それらにフィードパス名を設定します。
find top-dir -type f -name 'file*.txt' -exec sh -c '
for pathname do
vim -c "%s/PATTERN/REPLACEMENT/gc" -c "wq" "$pathname"
done' sh {} +
find top-dir -type f -name 'file*.txt' -exec sh -c '
for pathname do
grep -q "PATTERN" "$pathname" &&
vim -c "%s/PATTERN/REPLACEMENT/gc" -c "wq" "$pathname"
done' sh {} +
あなたは、どのような場合には、ないないような何かをしたいfor filename in $( grep -rl ... )
から
grep
ループの最初の反復を開始する前に実行を終了する必要がありますが、これはエレガントではありません。grep
空白文字の単語に分割され、これらの単語はファイル名のグロビングを受けます(これは、スペースと特殊文字を含むパス名を無効にします)。関連:
sed
は、複数のファイル、sed -i 's/old/new/g' /path/to/*.txt
または類似のファイルで操作できることです。
for i in $(grep -rl "old"); do vim -c "%s/old/new/gc" -c "wq" "$i"; done
これを行うことでこれを取得できます:
:%s/OLD_TEXT/NEW_TEXT/gc
具体的にはc
、3番目の区切り文字の後に追加します。
'c'オプションはVimでのみ機能することに注意してください。sed
コマンドラインで使用することはできません。
sed
。
vim
ため、この回答は適用可能です。ただし、明らかにvimとsedには異なる能力があります
sed
ファイルでその処理を実行させ、結果を一時ファイルに保存してから、元のファイルにインタラクティブにパッチを適用できますsdiff
(http://www.gnu.org/software/diffutils/manual/diffutils.htmlを参照してください#Invoking-sdiff):
sed -r 's/something/something_else/g' my_file > tmp_file
sdiff -o my_file -s -d my_file tmp_file
searchandreplace () {
if [ -z $2 ] ; then
realpath * | xargs grep -ins --directories=skip --color=always "$1" | nl -s "."
else
realpath * | xargs grep -ins --directories=skip --color=always "$1" | nl -s "."
exp=$(realpath * | xargs grep -ins --directories=skip --color=never "$1" | cut -d':' -f1,2 | awk -F':' '{print $2 $1}' | sed -E "s|^[0-9]+|sed -i \'&s/|; s|//|/"$1"/"$2"/g\' /|")
IFS=$'\n'
for d in $exp
do
read -p "Exec $(echo -e -n "\033[1;31m$d\033[0m")? " -e REP
if [ "$REP" = y ]; then
echo `bash -c $d`;
fi
done
fi
}
これを単一の引数でフィードする場合-- searchandreplace "AAA"
現在のディレクトリでその文字列のみを検索しますが、二重の引数でフィードする場合searchandreplace AAA BBB
--上記に加えて、最初の文字列を2番目の "line by行ごとに