Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/72.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
Bash 使用tr删除反斜杠_Bash_Macos_Tr - Fatal编程技术网

Bash 使用tr删除反斜杠

Bash 使用tr删除反斜杠,bash,macos,tr,Bash,Macos,Tr,因此,我将从文件名中删除特殊字符并替换为空格。除了包含单个反斜杠的文件之外,我还有其他工作。 注意:这些文件是在OSX上的Finder中创建的 old_name="testing\this\folder" new_name=$(echo $old_name | tr '<>:\\#%|?*' ' '); old\u name=“testing\this\folder” 新名称=$(echo$旧名称| tr':\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\?*'')

因此,我将从文件名中删除特殊字符并替换为空格。除了包含单个反斜杠的文件之外,我还有其他工作。 注意:这些文件是在OSX上的Finder中创建的

old_name="testing\this\folder"
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
old\u name=“testing\this\folder”
新名称=$(echo$旧名称| tr':\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\?*'');
这导致新的_名称被“测试他的父亲”
如何删除反斜杠而不是前面的字符?

对于Bash,可以使用参数展开:

$ old_name="testing\this\folder"
$ new_name=${old_name//[<>:\\#%|?*]/ }
$ echo $new_name
testing this folder
$old\u name=“测试\此\文件夹”
$new\u name=${old\u name/[:\\\\\\\\35;%\\\?*]/}
$echo$新名称
正在测试此文件夹

有关更多信息,请参阅上的Bash手册。

我认为您的测试用例缺少对
\
的正确转义,因此您没有真正测试字符串中包含反斜杠的情况

这对我很有用:

old_name='testing\\this\\folder'
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
echo $new_name
# testing this folder
old\u name='testing\\this\\folder'
新名称=$(echo$旧名称| tr':\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\?*'');
echo$new_名称
#正在测试此文件夹
这导致新的_名称被“测试他的父亲”

此字符串看起来像是
echo-e“测试\This\folder”
的结果,因为
\t
\f
实际上被制表符和表单提要控制字符替换

您可能有一个别名,如
alias echo='echo-e'
,或者您的shell版本中的
echo
的实现解释了反斜杠转义:

POSIX不需要支持任何选项,并表示 如果任何字符串包含 反斜杠或如果第一个参数为“-n”。可移植程序可以使用 如果需要省略尾随换行符或输出,则使用“printf”命令 控制字符或反斜杠

(从信息页面)

因此,您应该在新软件中使用
printf
而不是
echo
。特别是,
echo$old\u name
应替换为
printf%s“$old\u name”

例如,有一个很好的解释

无需
printf

正如@mklement0所建议的,您可以通过以下方式避免管道:

tr':\\\\#%|?*'解释了为什么您的命令可能不适用于您,并提供了一个健壮、可移植的解决方案

tl;博士

  • 您可能在运行代码时使用了
    sh
    而不是
    bash
    (即使在macOS上
    sh
    是bash的伪装),或者您显式启用了shell选项
    xpg\u echo
  • 为了便于携带,请使用
    printf
    而不是
    echo

在Bash中,使用默认选项并使用内置的
echo
时,命令应该按原样工作(除了为了稳健性,应该使用双引号
$old\u name
),因为默认情况下
echo
不会在其操作数中展开转义序列,例如
\t

但是,可以使用Bash的
echo
来扩展控制字符转义序列:

  • 显式地,通过执行shopt-s xpg_echo
  • 隐式地,如果您以
    sh
    或使用
    --posix
    选项运行Bash(在其他选项和行为更改中,它会激活
    xpg\u echo
  • 因此,您的症状可能是由使用shebang line
    #从脚本运行代码引起的/例如,bin/sh

    但是,如果您的目标是
    sh
    ,也就是说,如果您正在编写一个可移植脚本,那么应该完全避免使用
    echo
    ,因为它的行为在不同的shell和平台上有所不同-请参阅Ruslan的
    printf
    解决方案


    顺便说一句:
    tr
    命令的一种更可靠的方法可能是白名单方法:只声明结果中明确允许的字符,并使用
    -C
    选项排除其他字符:

    old_name='testing\this\folder'
    new_name=$(printf '%s' "$old_name" | tr -C '[:alnum:]_-' ' ')
    

    这样,任何不是字母、数字、
    \u
    -
    的字符都会被替换为空格。

    根据您定义特殊字符的方式,您可以在Bash中使用类似于
    tr-d'[:punch:]'
    的东西(问题是如何标记的),并使用默认选项,使用它的
    echo
    内置项,这将保留两个反斜杠,结果字符串的单词之间将有2个空格。(相反,OP的代码应该按原样工作。)除此之外,
    $old_name
    应该被双引号引用。您的转义只能在启用选项
    xpg_echo
    时(隐式或显式)才起作用,但更好的解决方案是使用
    printf
    或here-string。谢谢您的详细解释,这对我也不起作用
    old_name='testing\this\folder'
    new_name=$(printf '%s' "$old_name" | tr -C '[:alnum:]_-' ' ')