web-dev-qa-db-ja.com

交換する前に、sedに確認を求めますか?

交換する前に、sedに確認を求める方法はありますか? vim内でreplaceを使用する場合の「c」に似たもの。

Sedはこれをまったく行いますか?

40
Yuvi

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 ... )のようなことをしたいので、

  1. ループの最初の反復inelegantを開始する前でも、grepが実行を終了する必要があります。
  2. grepによって返されるパス名は空白で単語に分割され、これらの単語はファイル名の展開を受けます(これにより、スペースと特殊文字を含むパス名が無効になります)。

関連:

41
Kusalananda

あなたはそのようなことでこれを得ることができます:

:%s/OLD_TEXT/NEW_TEXT/gc

具体的には、3番目の区切り文字の後にcを追加します。

'c'オプションはVimでのみ機能することに注意してください。コマンドラインでsedを使用することはできません。

7
Kevin M

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
4
phk