使用MacOSX上的bash将多个文件中的字符串替换为相应的大写
我有多个.txt文件,我想在其中替换字符串使用MacOSX上的bash将多个文件中的字符串替换为相应的大写,macos,bash,awk,sed,Macos,Bash,Awk,Sed,我有多个.txt文件,我想在其中替换字符串 old -> new Old -> New OLD -> NEW 第一步是只替换一个字符串Old->New。这是我当前的代码,但它不起作用(文件保持不变)。只有用实际字符串替换变量时,sed行才起作用 #!/bin/bash old_string="Old" new_string="New" sed -i '.bak' 's/$old_string/$new_string/g' *.txt 另外,如何将字符串转换为所有大写字母和
old -> new
Old -> New
OLD -> NEW
第一步是只替换一个字符串Old->New。这是我当前的代码,但它不起作用(文件保持不变)。只有用实际字符串替换变量时,sed行才起作用
#!/bin/bash
old_string="Old"
new_string="New"
sed -i '.bak' 's/$old_string/$new_string/g' *.txt
另外,如何将字符串转换为所有大写字母和所有小写字母
非常感谢你的建议 如果要在
sed
的参数内执行bash
变量扩展,则需要使用双引号“
而不是单引号”
sed -i '.bak' "s/$old_string/$new_string/g" *.txt
就获得所有三个文字替换的匹配而言,最干净的解决方案可能就是在这样的循环中运行sed
三次
declare -a olds=(old Old OLD)
declare -a news=(new New NEW)
for i in `seq 0 2`; do
sed -i "s/${olds[$i]}/${news[$i]}/g" *.txt
done;
更新:上述解决方案在Linux上运行,但显然OSX
有不同的要求。此外,正如@mklement0所提到的,我的for
循环很愚蠢。下面是OSX
的改进版本
declare -a olds=(old Old OLD)
declare -a news=(new New NEW)
for (( i = 0; i < ${#olds[@]}; i++ )); do
sed -i '.bak' "s/${olds[$i]}/${news[$i]}/g" *.txt
done;
declare-a olds=(old)
声明-a新闻=(新建)
对于((i=0;i<${olds[@]};i++),do
sed-i'.bak''s/${olds[$i]}/${news[$i]}/g“*.txt
完成;
如果要在sed
的参数内部执行bash
变量扩展,则需要使用双引号“
而不是单引号”
sed -i '.bak' "s/$old_string/$new_string/g" *.txt
就获得所有三个文字替换的匹配而言,最干净的解决方案可能就是在这样的循环中运行sed
三次
declare -a olds=(old Old OLD)
declare -a news=(new New NEW)
for i in `seq 0 2`; do
sed -i "s/${olds[$i]}/${news[$i]}/g" *.txt
done;
更新:上述解决方案可以在Linux上运行,但显然OSX
有不同的要求。此外,正如@mklement0所提到的,我的for
循环很愚蠢。这是一个针对OSX
的改进版本
declare -a olds=(old Old OLD)
declare -a news=(new New NEW)
for (( i = 0; i < ${#olds[@]}; i++ )); do
sed -i '.bak' "s/${olds[$i]}/${news[$i]}/g" *.txt
done;
declare-a olds=(old)
声明-a新闻=(新建)
对于((i=0;i<${olds[@]};i++);做
sed-i'.bak''s/${olds[$i]}/${news[$i]}/g“*.txt
完成;
补充@merlin2011的有用答案:
如果要动态创建案例变体,请尝试以下操作:
# Define search and replacement strings
# as all-lowercase.
old_string='old'
new_string='new'
# Loop 3 times and create the case variants dynamically.
# Build up a _single_ sed command that performs all 3
# replacements.
sedCmd=
for (( i = 1; i <= 3; i++ )); do
case $i in
1) # as defined (all-lowercase)
old_string_variant=$old_string
new_string_variant=$new_string
;;
2) # initial capital
old_string_variant="$(tr '[:lower:]' '[:upper:]' <<<"${old_string:0:1}")${old_string:1}"
new_string_variant="$(tr '[:lower:]' '[:upper:]' <<<"${new_string:0:1}")${new_string:1}"
;;
3) # all-uppercase
old_string_variant=$(tr '[:lower:]' '[:upper:]' <<<"$old_string")
new_string_variant=$(tr '[:lower:]' '[:upper:]' <<<"$new_string")
;;
esac
# Append to the sed command string. Note the use of _double_ quotes
# to ensure that variable references are expanded.
sedCmd+="s/$old_string_variant/$new_string_variant/g; "
done
# Finally, invoke sed.
sed -i '.bak' "$sedCmd" *.txt
为了补充@merlin2011的有用答案: 如果要动态创建案例变体,请尝试以下操作:
# Define search and replacement strings
# as all-lowercase.
old_string='old'
new_string='new'
# Loop 3 times and create the case variants dynamically.
# Build up a _single_ sed command that performs all 3
# replacements.
sedCmd=
for (( i = 1; i <= 3; i++ )); do
case $i in
1) # as defined (all-lowercase)
old_string_variant=$old_string
new_string_variant=$new_string
;;
2) # initial capital
old_string_variant="$(tr '[:lower:]' '[:upper:]' <<<"${old_string:0:1}")${old_string:1}"
new_string_variant="$(tr '[:lower:]' '[:upper:]' <<<"${new_string:0:1}")${new_string:1}"
;;
3) # all-uppercase
old_string_variant=$(tr '[:lower:]' '[:upper:]' <<<"$old_string")
new_string_variant=$(tr '[:lower:]' '[:upper:]' <<<"$new_string")
;;
esac
# Append to the sed command string. Note the use of _double_ quotes
# to ensure that variable references are expanded.
sedCmd+="s/$old_string_variant/$new_string_variant/g; "
done
# Finally, invoke sed.
sed -i '.bak' "$sedCmd" *.txt
假设每个字符串与其他字符串之间用空格分隔,并且不希望在较长的字符串中进行部分匹配,也不关心在输出中保留空白,并且假设在上一次转换操作后,如果“旧”字符串与“新”字符串匹配,则应再次更改该字符串:
$ cat tst.awk
BEGIN {
split(tolower(old),oldStrs)
split(tolower(new),newStrs)
}
{
for (fldNr=1; fldNr<=NF; fldNr++) {
for (stringNr=1; stringNr in oldStrs; stringNr++) {
oldStr = oldStrs[stringNr]
if (tolower($fldNr) == oldStr) {
newStr = newStrs[stringNr]
split(newStr,newChars,"")
split($fldNr,fldChars,"")
$fldNr = ""
for (charNr=1; charNr in fldChars; charNr++) {
fldChar = fldChars[charNr]
newChar = newChars[charNr]
$fldNr = $fldNr ( fldChar ~ /[[:lower:]]/ ?
newChar : toupper(newChar) )
}
}
}
}
print
}
注意,“阴燃”中的“旧”并没有改变。这是可取的吗
$ awk -v old="QUIck Fox" -v new="raBid DOG" -f tst.awk file
The old Old OLD smOLDering RaBId brown DoG jumped
$ awk -v old="THE brown Jumped" -v new="FEW dingy TuRnEd" -f tst.awk file
Few old Old OLD smOLDering QuICk dingy FoX turned
想想这是否是您的预期输出:
$ awk -v old="old new" -v new="new yes" -f tst.awk file
The yes Yes YES smOLDering QuICk brown FoX jumped
问题中的几行示例输入和预期输出将有助于避免所有猜测和假设。假设每个字符串由空格与其他字符串分隔,并且不希望在较长的字符串中进行部分匹配,并且不关心在输出上保留空白,并假设在上一次转换操作后,“旧”字符串与“新”字符串匹配,然后应再次更改该字符串:
$ cat tst.awk
BEGIN {
split(tolower(old),oldStrs)
split(tolower(new),newStrs)
}
{
for (fldNr=1; fldNr<=NF; fldNr++) {
for (stringNr=1; stringNr in oldStrs; stringNr++) {
oldStr = oldStrs[stringNr]
if (tolower($fldNr) == oldStr) {
newStr = newStrs[stringNr]
split(newStr,newChars,"")
split($fldNr,fldChars,"")
$fldNr = ""
for (charNr=1; charNr in fldChars; charNr++) {
fldChar = fldChars[charNr]
newChar = newChars[charNr]
$fldNr = $fldNr ( fldChar ~ /[[:lower:]]/ ?
newChar : toupper(newChar) )
}
}
}
}
print
}
注意“阴燃”中的“旧”并没有改变。这是可取的吗
$ awk -v old="QUIck Fox" -v new="raBid DOG" -f tst.awk file
The old Old OLD smOLDering RaBId brown DoG jumped
$ awk -v old="THE brown Jumped" -v new="FEW dingy TuRnEd" -f tst.awk file
Few old Old OLD smOLDering QuICk dingy FoX turned
想想这是否是您的预期输出:
$ awk -v old="old new" -v new="new yes" -f tst.awk file
The yes Yes YES smOLDering QuICk brown FoX jumped
问题中的几行示例输入和预期输出将有助于避免所有猜测和假设。感谢merlin,这可以将“旧”替换为“新”。不过,我还想转换其他情况,而不必定义6个变量。(我有大量的词要替换)。我可以将旧的字符串变量转换为所有大写字母吗?谢谢!+1,但是OSX
sed
需要-I'
(注意所需的空间)在不创建备份文件的情况下就地修改(第二个代码段);另外,对于I in$(seq 02)
有点痛;我可以建议((I=0;I<${olds[@]};I++)使用)
?@mklement0,谢谢。我会进行编辑。我没有访问OSX的权限,所以我会采纳你的建议。:)谢谢你的更新;事实上,这应该是'
而不是'
来禁止创建备份文件(抱歉-按“所需空间”)“我的意思是您需要-I
和空字符串'
)之间的空格。但是您可以坚持使用-i'.bak'
,作为您的第一个代码段,它也适用于OSX。@user2926577,如果您试图使它成为不区分大小写的匹配,您可以将/i
标志添加到s
命令的末尾。例如,如果您想在用NEw
替换OLd
时以某种方式复制案例,那么我认为您必须使用一个更强大的工具。谢谢merlin,这可以将“OLd”替换为“NEw”。但是,我还想转换其他情况,而不必定义6个变量。(我有一大堆话要替换)。我是否可以以某种方式将旧的_字符串变量转换为所有大写字母?谢谢+1,但OSXsed
要求-i'
(注意所需的空间)在不创建备份文件的情况下就地修改(第二个代码段);另外,对于美元中的i(seq 02)
有点痛;我可以为((I=0;I<${olds[@]};I++)推荐。
?@mklement0,谢谢。我将进行编辑。我没有访问OSX的权限,因此我将接受您对faith的建议。:)谢谢你的更新;实际上,这应该是'
而不是'
来禁止创建备份文件(对不起,我说的“所需空间”是指您需要-I
和空字符串'
之间的空间)。但是您可以坚持使用-i'.bak'
,作为您的第一个代码段,它也适用于OSX。@user2926577,如果您试图使它成为不区分大小写的匹配,您可以将/i
标志添加到s
命令的末尾。如果你想以某种方式复制