2

我正在尝试编写一个基本上像 Microsoft 单词 find>replace 函数一样工作的脚本。它首先要求用户提供两个输入。第一个用于查找字符串,第二个用于替换旧字符串。尽管这很简单,但我也想计算要替换的东西的数量并回显用户以确认这些具体的替换数量。我怎样才能做到这一点?到目前为止,我将其作为搜索>替换功能:

for file in `find -name '*.sdf.new'`;  
do  
    grep "$search" $file &> /dev/null  
    sed -i "s/$search/$replace/" $file  
done
4

2 回答 2

0
check_val=`grep "$search" $file`
if [[ "x$check_val" != "x" ]]
then
        read -p "replace ?" response;
        if [[ "$response" == "y" ]]
        then
                sed -i "s/$search/$replace/" $file
        fi
fi
于 2013-07-17T12:16:27.317 回答
0
while read -u 3 -r -d '' file; do
    n=$(grep -o "$search" "$file" | wc -l)
    read -p "About to replace $n instances of '$search' in $file. OK? " ans
    if [[ $ans == [yY]* ]]; then
        sed -i "s|${search//|/\\\\|}|${replace//|/\\\\|}|g" "$file"
    fi
done 3< <(find -name '*.sdf.new' -print0)

这里发生了一些棘手的事情:

  • find 命令的输出被发送到文件描述符 3 上的 while 循环,并且 read 使用该 fd 来获取文件名
    • 这是必要的,因为循环中有一个读取命令可以与必须使用标准输入的用户进行交互。
  • while 循环从进程替换 中读取,<(find -name ...)因此不必创建子 shell 并便于使用不同的文件描述符。
    • 在 bash 中,当您说 时cmd1 | cmd2,会为管道的每一侧创建新的 bash 进程。这可能会导致在子 shell 中分配的变量在当前 shell 中不存在的问题,这里不是这种情况。
  • 为了正确处理具有奇怪名称的文件,我使用了 GNU 查找-print0功能,它用零字节分隔文件名,然后使用读取-d ''选项。
  • grep -c计算匹配的行数。grep -o pattern file | wc -l计算实际匹配的数量。
  • 如果搜索或替换字符串包含s命令分隔符,疯狂的 sed 脚本会增加保护。我使用|而不是/因为转义变得更加极端。
于 2013-07-17T13:50:00.143 回答