Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.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
变量操作在macOS bash脚本中未按预期工作_Bash_Macos_Sed - Fatal编程技术网

变量操作在macOS bash脚本中未按预期工作

变量操作在macOS bash脚本中未按预期工作,bash,macos,sed,Bash,Macos,Sed,鉴于: 我想在删除不可打印内容的同时将八进制转换为可打印内容。问题:我不想删除像\b这样的反斜杠字母。结果应该是: itemName='boo\boo\1\7\064.txt' 我不明白为什么sed语句的一部分不能正常工作: newItemName='boo\boo4.txt' 我使用了somevar=“&”而不是直接访问和,因此我可以使用变量操作 搜索语句s/(\[0-7]{1,3})/工作正常 在printf中,如果我使用$somevar或${somevar:0}而不是${somevar

鉴于:

我想在删除不可打印内容的同时将八进制转换为可打印内容。问题:我不想删除像\b这样的反斜杠字母。结果应该是:

itemName='boo\boo\1\7\064.txt'
我不明白为什么sed语句的一部分不能正常工作:

newItemName='boo\boo4.txt'
我使用了somevar=“&”而不是直接访问,因此我可以使用变量操作

搜索语句s/(\[0-7]{1,3})/工作正常

在printf中,如果我使用$somevar${somevar:0}而不是${somevar:1}我会得到预期的原始字符串(例如.\064)。 不起作用的是${somevar:1}。 这些也不起作用:${somevar/\/}${somevar/\/}

  • 我对变量操作的工作原理有什么误解
  • 有没有更简单的方法?我找了又找
  • 我对变量操作的工作原理有什么误解

    我相信你误解了sed的工作原理

    当替换字符串中使用
    &
    字符时,它将被匹配的整个字符串替换。看

    现在关于:

    将打印
    &
    。然后:

    somevar=&
    printf "$somevar" 
    
    将从偏移量1到字符串末尾提取子字符串。第一个字符位于偏移量0处,因此在偏移量1处没有字符,因为out变量
    somevar
    有一个字符。所以它不会打印任何内容

    printf "${somevar:1}"
    
    将打印从偏移量0开始到字符串末尾的子字符串。因此,整个字符串。所以
    ${somevar:0}
    等于
    $somevar
    。它将打印
    &

    因此:

    扩展为零,因为
    ${somevar:1}
    扩展为零。因此,sed命令如下所示:

    $(somevar="&";printf "${somevar:1}";)
    
    $(somevar="&";printf "${somevar:0}";)
    
    sed命令将一个
    \
    字符后跟一个数字
    0-7
    一到三次替换为零,多次。它做你想要的

    现在,如果它是
    ${somevar:0}
    ,那么:

    sed -E 's/(\\[0-7]{1,3})//g' 
    
    扩展到
    &
    ,因此您的sed命令如下所示:

    $(somevar="&";printf "${somevar:1}";)
    
    $(somevar="&";printf "${somevar:0}";)
    
    因此它将用一个
    \\[0-7]{1,3}
    来代替它本身。它什么也没做

    您可以松开
    -E
    选项和
    (…)
    反向引用,只需使用posixly兼容的
    sed

    sed -E 's/(\\[0-7]{1,3})/&/g' 
    
    有没有更简单的方法

    你的方法看起来不错。您可以使用a而不是printf,并且可以根据需要加强sed以更好地匹配八进制数:

    sed 's/\\[0-7]\{1,3\}//g'
    
    newItemName=”$(
    
    Sam;好久不见!这里的问题是求值顺序。所有的shell表达式,包括
    $(somevar=“&”printf“${somevar:1}”)
    ,都是在sed启动之前求值的。因此,
    somevar
    不是正则表达式匹配的字符串,它只是一个文字符号。这意味着
    ${somevar:1}
    只是一个空字符串,您只需运行
    sed-E/(\\[0-7]{1,3})//g'

    您需要一种方法来获取匹配的字符串并对其运行计算(在匹配后),sed不够灵活。但是perl是。perl有一个
    s
    操作符,与sed类似,但是使用
    e
    选项,替换将作为perl表达式而不是文字字符串执行。请尝试一下:

    newItemName="$(
            <<<"$itemName" sed 's/\\\([0-3][0-7]\{0,2\}\|[0-7]\{1,2\}\)//g' |
            tr -dc '[:print:]'
    )"
    

    sed-E
    -请检查您在macos上是否有
    sed-E
    。似乎没有-E.@SamuelHerschbein,这只会产生一个文本
    &
    ,因此这就是传递给
    sed
    作为替换的内容。尝试在它之前运行
    set-x
    (在macOS上,
    unset PROMPT_命令
    删除后台聊天),shell将打印其实际执行的内容。使用
    set+x
    将其关闭。
    newItemName="$(printf "%s\n" "$itemName" | perl -pe 's/\\([0-7]{1,3})/chr oct $1/eg' | tr -dc '[:print:]')"