我如何查找并替换每次出现的:

subdomainA.example.com

具有

subdomainB.example.com

递归地在/home/www/目录树下的每个文本文件中?


当前回答

对我来说最简单的方法是

grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'

其他回答

试试看:

sed -i 's/subdomainA/subdomainB/g' `grep -ril 'subdomainA' *`

对于IBMi上的Qshell(qsh),不是OP标记的bash。

qsh命令的限制:

find没有-print0选项xargs没有-0选项sed没有-i选项

因此,qsh中的解决方案:

    PATH='your/path/here'
    SEARCH=\'subdomainA.example.com\'
    REPLACE=\'subdomainB.example.com\'

    for file in $( find ${PATH} -P -type f ); do

            TEMP_FILE=${file}.${RANDOM}.temp_file

            if [ ! -e ${TEMP_FILE} ]; then
                    touch -C 819 ${TEMP_FILE}

                    sed -e 's/'$SEARCH'/'$REPLACE'/g' \
                    < ${file} > ${TEMP_FILE}

                    mv ${TEMP_FILE} ${file}
            fi
    done

注意事项:

解决方案不包括错误处理不是OP标记的Bash

这一个与git存储库兼容,而且更简单:

Linux:

git grep -l 'original_text' | xargs sed -i 's/original_text/new_text/g'

Mac:

git grep -l 'original_text' | xargs sed -i '' -e 's/original_text/new_text/g'

(感谢http://blog.jasonmeridth.com/posts/use-git-grep-to-replace-strings-in-files-in-your-git-repository/)

更简单的方法是在命令行上使用以下命令

find /home/www/ -type f|xargs perl -pi -e 's/subdomainA\.example\.com/subdomainB.example.com/g' 

用更简单的fd(1)/fdfind=替换find(1)https://github.com/sharkdp/fd:

fdfind . --type f --exec sed -i "s/original_string/new_string/g"

寻址fd(1)iconsistent pkg和cmd名称

在macOS自制软件上:pkg和cmd=fd在Ubuntu 20.04上:pkg=fd find,cmd=fdfind

我在macOS上创建了一个别名fdfind='fd',以实现一致的cmd命名(在我的macOS和Linux平台之间)。

有关这一点的更多信息,请访问https://github.com/sharkdp/fd/issues/1009.

更多细节和附加功能

# bash examples:

1='original_string'
2='new______string'

# for this (the original-poster's) question:
1='subdomainA.example.com'
2='subdomainB.example.com'

# 'fdfind' (on at least Ubuntu 20.04) = 'fd' = https://github.com/sharkdp/fd

fdfind . --type f --exec sed -i "s/$1/$2/g"

# Here's a slightly-more-complex example that
# a. excludes (-E) .git/ and archive/ dirs, and
# b. performs a word-boundary search on the original_string (\<$1\>):
fdfind . -E .git/ -E archive/ --type f --exec sed -i "s/\<$1\>/$2/g"

甚至更高级:从第三个($3)命令行参数控制单词边界(第三个参数=noword表示无边界,leftword表示仅左侧单词边界,rightword表示仅右侧边界):

#!/usr/bin/env bash

#
# replace-tree.bash
#

# 'fdfind' (on at least Ubuntu 20.04) = 'fd' = https://github.com/sharkdp/fd

if [ $# -lt 2 ]; then
  echo "$0: Please provide at least 2 arguments."
  exit 1
fi

original="\<$1\>"

if   [ "$3" = "noword" ];    then
  original="$1"
elif [ "$3" = "leftword" ];  then
  original="\<$1"
elif [ "$3" = "rightword" ]; then
  original="$1\>"
fi

fdfind . --type f --exec sed -i "s/$original/$2/g"

示例用法:

$ replace-tree.bash original_string new_string leftword
$