让 sed 在每次替换之前要求确认?

让 sed 在每次替换之前要求确认?

有没有办法让 sed 在每次替换之前询问我确认?在 vim 中使用替换时类似于“c”。

sed 真的这样做吗?

答案1

使用它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

上述两个 shell 循环修改为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' {} \;

或者,使用原始 shell 循环并将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

你可以通过这样做来得到这个:

:%s/OLD_TEXT/NEW_TEXT/gc

c具体来说,在第三个分隔符之后添加。

请注意,'c' 选项仅在 Vim 中有效;您将无法sed在命令行中使用它。

答案3

您可以让其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

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– 那么除了上述之外,它还要求您用第二个“line by”替换第一个行”对于每一行。

相关内容