各交換の前にsedに確認を求めますか?


37

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

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


3
技術的には可能ですが、有益な努力というよりも知的運動の方が多いでしょう。大きなフォルダー階層でテキストを置換する方法をご覧くださいVimおよびPerlソリューションがあります。
ジル「SO-悪であるのをやめる」

私は午前 vimの(引数をとargdo)を使用して、私は「確認」を必要なときが、「単純」な方法があったか疑問に思った
Yuvi

1
sedの基本的な目的に反する-ストリームの編集を自動化する。
テプピック

@teppicは、テキストファイルでインスタンスを見つける必要があるため、実際にはそうではありません。sedを使用すると便利です。私はあなたのリストに間違ったファイルを追加し、あなたが編集していた何のファイルを見てみたかっただけの場合には、質問は理にかなっていると思います
Kolobキャニオン

回答:


37

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. grepループの最初の反復を開始する前に実行を終了する必要がありますが、これはエレガントではありません
  2. によって返されるパス名はgrep空白文字の単語に分割され、これらの単語はファイル名のグロビングを受けます(これは、スペースと特殊文字を含むパス名を無効にします)。

関連:


2
利点sedは、複数のファイル、sed -i 's/old/new/g' /path/to/*.txtまたは類似のファイルで操作できることです。
user1717828

10
for i in $(grep -rl "old"); do vim -c "%s/old/new/gc" -c "wq" "$i"; done
tcpaiva

@tecepe、回答に変換してください、ありがとう。
Nishant

1
@Nishant名前またはパスに空白が含まれているファイルは失格となるため、脆弱な回答になります。
クサラナナンダ

7

これを行うことでこれを取得できます:

:%s/OLD_TEXT/NEW_TEXT/gc

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

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


4
明確にするために:これはVimでのみ機能し、通常のコマンドラインでは機能しませんsed
ブレンダン

OPはでタグ付けされているvimため、この回答は適用可能です。ただし、明らかにvimとsedには異なる能力があります
ILMostro_7


-1
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行ごとに

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