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


37

有没有办法让sed在每次更换之前要求我确认?在vim中使用replace时,类似于'c'的东西。

sed会这样做吗?


3
从技术上讲这是可能的,但更多的是智力上的努力,而不是有益的努力。请参阅如何在大文件夹层次结构中进行文本替换?具有Vim和Perl解决方案。
吉尔斯(Gillles)“所以-别再邪恶了”,

每当需要“确认”时,我都使用vim(args和argdo),但想知道是否存在“更简单”的方式
Yuvi

1
它违背了sed的基本目的-自动编辑流。
teppic 2015年

@teppic并不是真的,因为您仍然必须在文本文件中查找实例,而sed可以为您执行这些操作。我认为这个问题很有意义,以防万一您将错误的文件添加到列表中并想查看您正在编辑的文件
Kolob Canyon

Answers:


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

上面的两个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循环并在其中添加findfeed路径名:

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在第三个定界符之后添加。

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


4
需要说明的是:这仅适用于Vim,不适用于常规命令行sed
布伦丹2015年

OP带有标记vim,因此该答案适用。但是,显然vim和sed具有不同的功能
ILMostro_7 2016年


-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–则除了上面的参数外,它还要求您将第一行替换为第二行每行”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.