批量 文本内容替换, 改文件名 shell 脚本

原文:批量文本内容替换, 改文件名 shell 脚本
作者:Breaker <breaker.zy_AT_gmail>


写了个 shell 脚本 repren.sh,替换当前目录下的文本文件(根据扩展名、文件名决定)中的字符串 OLD_TEXT 为 NEW_TEXT,将含 OLD_TEXT 的文件名重命名为 NEW_TEXT

用途例子:改变 VC 工程中的工程名
改进说明:可将 FIND_REGEX(文件扩展名)、SED_REGEX(文本边界)、GREP_REGEX(文件名边界)的选择作为脚本命令选项, 或从另一文件中读取配置
限制说明:只是个文本替换小模型,没测中文

功能

假设如此调用脚本 repren.sh:

repren.sh Tom JerryOLD_TEXT=Tom
NEW_TEXT=Jerry

按顺序做以下一些事:

1. 查找目录及子目录中的以下文件(大小写无关):

  • 文件名是:makefile、readme

  • 扩展名是:

    .h、.hxx、.hpp、.c、.cpp、.cxx
    .txt
    .mak、.rc
    .xml、.html、.xhtml
    .sln、.vcproj

查找的文件名正则表达式规则在 FIND_REGEX 中定义

2. 将找到的文件中的文本 Tom 替换为 Jerry:

Tom => Jerry: 严格大小写替换
TOM => JERRY: 全大写替换
tom => jerry: 全小写替换

但不替换:
tOm => Jerry: 混合大小写替换

Tom 两边可以有新行、空格、TAB、数字 0-9,以及这些 ASCII 标准标点符号

. , : ; _ - = + * ~ ! @ # $ % ^ & ' " < > [ ] ( ) { } / \ ? ` |

此时都可成功替换

但不能替换:
aaTombb => aaJerrybb
此时可修改 SED_REGEX='\(\b\|[0-9a-zA-Z_]\)',上面替换即可成功进行,但也会做下面替换:
Tomorrow => Jerryorrow

2. 对上面的文件,如果文件名中含 Tom,将其重命名为 Jerry

重命名支持混合大小写替换,即:
tOm_test.cpp => Jerry_test.cpp

重命名时,Tom 两边可以有的字符和 1 相同
不能替换:
TomTest.cpp => JerryTest.cpp
此时可修改 GREP_REGEX='(\b|[0-9a-zA-Z_]),但也会做下面替换:
Tomorrow.cpp => Jerryorrow.cpp

3. 对于当前目录下的所有子目录的目录名,做和 2 相同的事

shell 脚本代码

#!/bin/bash

################################################################################
# Name: repren.sh
# Description:
# 按顺序做以下事情:
# 1. 查找特定类型的文件,如 .h、.cpp
# 2. 将文件内容中的文本 OLD_TEXT 替换成 NEW_TEXT
# 3. 将含 OLD_TEXT 的文件名重命名为 NEW_TEXT
# 4. 将含 OLD_TEXT 的目录名重命名为 NEW_TEXT
#
# Author: Breaker <breaker.zy_AT_gmail>
# Date: 2011-10
################################################################################

# IFS 表示 for 语句中各项之间的分隔符
OLDIFS = $IFS
IFS = $'\n' # $ 使字面量启动转义,否则 \n 为直接字面量而非 LF
SCRIPT_NAME = `basename "$0" `

# 用法
usage()
{
echo "usage:"
echo " $SCRIPT_NAME OLD_TEXT NEW_TEXT"
}

if [ $# -lt 2 ]; then
usage
exit -1
fi

# 替换前后的 文本
OLD_TEXT = "$1"
NEW_TEXT = "$2"

OLD_TEXT_UPPER = ` echo $OLD_TEXT | tr '[a-z]' '[A-Z]' ` # 全大写的 旧文本
OLD_TEXT_LOWER = ` echo $OLD_TEXT | tr '[A-Z]' '[a-z]' ` # 全小写的 旧文本

NEW_TEXT_UPPER = ` echo $NEW_TEXT | tr '[a-z]' '[A-Z]' ` # 全大写的 新文本
NEW_TEXT_LOWER = ` echo $NEW_TEXT | tr '[A-Z]' '[a-z]' ` # 全小写的 新文本

echo -e 'replace text & rename file ...\n'

# 查找指定文件
FIND_REGEX = '.*(/(makefile|readme)|\.(h|hxx|hpp|c|cpp|cxx|txt|mak|rc|x(ht)?ml|html?|sln|vcproj))'
FILES = `find -type f -regextype posix-egrep -iregex "$FIND_REGEX" `

# 文本替换时的 字符串边界
#SED_REGEX='\(\b\|_\)'
SED_REGEX = '\(\b\|[0-9_]\)'
#SED_REGEX='\(\b\|[0-9a-zA-Z_]\)'

# 重命名时的 文件名边界
#GREP_REGEX='(\b|_)'
GREP_REGEX = '(\b|[0-9_])'
#GREP_REGEX='(\b|[0-9a-zA-Z_])'

# 对每个查找到的文件去做...
for EACH in $FILES
do
# 替换文件中的文本 OLD_TEXT 为 NEW_TEXT
sed -i "s/$SED_REGEX$OLD_TEXT$SED_REGEX/\1$NEW_TEXT\2/g" $EACH
sed -i "s/$SED_REGEX$OLD_TEXT_UPPER$SED_REGEX/\1$NEW_TEXT_UPPER\2/g" $EACH
sed -i "s/$SED_REGEX$OLD_TEXT_LOWER$SED_REGEX/\1$NEW_TEXT_LOWER\2/g" $EACH
echo "$EACH: replace: $OLD_TEXT => $NEW_TEXT"

# 重命名含 OLD_TEXT 的文件名为 NEW_TEXT
OLD_FILE_0 = `basename $EACH | grep -E -i "$GREP_REGEX$OLD_TEXT$GREP_REGEX" ` # 只针对文件名,不管目录部分
if [ "$OLD_FILE_0" ! = "" ]; then
DIR = `dirname $EACH `
OLD_FILE = "$DIR/$OLD_FILE_0"

NEW_FILE_0 = ` echo "$OLD_FILE_0" | sed "s/$OLD_TEXT/$NEW_TEXT/gi" `
NEW_FILE = "$DIR/$NEW_FILE_0"

mv "$OLD_FILE" "$NEW_FILE"
echo "rename: $OLD_FILE => $NEW_FILE"
fi

echo ''
done

echo -e 'rename dir ...\n'

# 更改目录名:重命名含 OLD_TEXT 的目录名
DIRS = `find -type d `
for EACH in $DIRS; do
OLD_DIR_0 = `basename $EACH | grep -E -i "$GREP_REGEX$OLD_TEXT$GREP_REGEX" `
if [ "$OLD_DIR_0" ! = "" ]; then
OLD_DIR_DIR = `dirname $EACH `
OLD_OLD_DIR = "$OLD_DIR_DIR/$OLD_DIR_0"

NEW_DIR_0 = ` echo "$OLD_DIR_0" | sed "s/$OLD_TEXT/$NEW_TEXT/gi" `
NEW_DIR_DIR = ` echo "$OLD_DIR_DIR" | sed "s/$OLD_TEXT/$NEW_TEXT/gi" `

# find 先输出父目录,所以父目录这时已经重命名了
# 所以 OLD_DIR 由新的父目录名和 OLD_DIR_0 拼成,而不是原来的 OLD_OLD_DIR 了
OLD_DIR = "$NEW_DIR_DIR/$OLD_DIR_0"
NEW_DIR = "$NEW_DIR_DIR/$NEW_DIR_0"

mv "$OLD_DIR" "$NEW_DIR"
echo "rename: $OLD_OLD_DIR => $NEW_DIR"
echo ''
fi
done

# 恢复环境
IFS = $OLDIFS

相关工具

25 Text Batch Processing Tools Reviewed: 25 种文本批量处理工具评估,文本查找、替换、正则表达式支持

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用 sed 命令来批量修改文件内容,以下是一个示例: ``` #!/bin/bash # 定义需要修改文件路径 file_path="/path/to/files/*.txt" # 定义需要替换的字符串和替换后的字符串 old_string="foo" new_string="bar" # 批量替换文件内容 sed -i "s/${old_string}/${new_string}/g" ${file_path} ``` 在上面的示例中,首先定义了需要修改文件路径,然后定义了需要替换的字符串和替换后的字符串。最后使用 sed 命令批量替换文件内容,其中 `-i` 表示直接修改文件内容,而不是输出到终端。`${old_string}` 和 `${new_string}` 是变量,用于替换 sed 命令中的字符串。`g` 表示全局替换,即一行中所有匹配的字符串都会被替换。 ### 回答2: Shell脚本可以方便地批量修改文件内容。可以通过以下步骤实现: 1. 构建一个循环来遍历要修改文件列表。可以使用通配符来匹配一定规则的文件,比如使用`*.txt`来匹配所有扩展名为txt文件。 2. 在循环中,使用`sed`命令来实现对文件内容修改。`sed`命令是一个强大的文本处理工具,可以通过正则表达式匹配要修改内容,并进行替换或者其他操作。 3. 在`sed`命令中,使用正则表达式匹配要修改内容,然后使用替换操作符将内容替换为新的内容。例如,`sed 's/old_content/new_content/g' file.txt`表示将文件file.txt中的所有old_content替换为new_content。 4. 可以在shell脚本中添加条件判断语句,来对不同的文件进行不同的修改操作。例如,可以根据文件名进行判断,如果是以ABC开头的文件,就执行一种修改操作,如果是以XYZ开头的文件,执行另一种修改操作。 5. 在循环结束后,可以打印出每个文件修改结果或者生成一个修改日志,方便后续查看和验证。 需要注意的是,在进行批量文件修改时,一定要备份原始文件,以防操作出现问题导致文件内容丢失或者不可恢复。另外,一定要小心操作,避免对不应该修改文件产生影响。 ### 回答3: shell脚本可以用于批量修改文件内容。通过使用循环结构和sed命令,可以实现对多个文件中特定内容替换修改。 首先,我们可以使用一个循环来遍历需要修改文件。可以使用通配符来匹配一组文件,也可以使用一个包含文件名的列表。例如,使用`for`循环遍历当前目录下的所有文本文件: ``` for file in *.txt do # 在这里进行文件内容修改 done ``` 接下来,使用sed命令来修改文件内容。sed是一个强大的流编辑器,可以用于查找和替换文件中的文本。假设我们要将文件中的"hello"替换为"world",可以使用以下命令: ``` sed -i 's/hello/world/g' $file ``` 其中,`-i`选项表示直接修改文件,`s/hello/world/g`表示查找字符串"hello"并替换为"world",`$file`表示当前迭代的文件名。 综上所述,如果我们想要批量修改一组文件的特定内容,我们可以编写一个包含循环和sed命令的shell脚本。在循环中指定需要修改文件列表,在sed命令中指定要查找和替换内容。通过这种方式,我们可以方便地批量修改文件内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值