Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用MacOSX上的bash将多个文件中的字符串替换为相应的大写_Macos_Bash_Awk_Sed - Fatal编程技术网

使用MacOSX上的bash将多个文件中的字符串替换为相应的大写

使用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 另外,如何将字符串转换为所有大写字母和

我有多个.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,但OSX
sed
要求
-i'
(注意所需的空间)在不创建备份文件的情况下就地修改(第二个代码段);另外,
对于美元中的i(seq 02)
有点痛;我可以为((I=0;I<${olds[@]};I++)推荐
?@mklement0,谢谢。我将进行编辑。我没有访问OSX的权限,因此我将接受您对faith的建议。:)谢谢你的更新;实际上,这应该是
'
而不是
'
来禁止创建备份文件(对不起,我说的“所需空间”是指您需要
-I
和空字符串
'
之间的空间)。但是您可以坚持使用
-i'.bak'
,作为您的第一个代码段,它也适用于OSX。@user2926577,如果您试图使它成为不区分大小写的匹配,您可以将
/i
标志添加到
s
命令的末尾。如果你想以某种方式复制