如何在bash中反转转义反斜杠编码,如“\”和“\ 303 \ 266”?

时间:2009-09-07 16:15:49

标签: linux bash encoding character-encoding escaping

我有一个脚本,用于记录UTF8编码名称的文件。但是,脚本的编码/环境设置不正确,它只是重新编码原始字节。我现在在文件中有很多行,如下所示:

.../My\ Folders/My\ r\303\266m/...

因此文件名中有\和UTF8编码的空格,如\303\266ö)。我想反转这种编码?是否有一些简单的bash命令行命令可以链接在一起以删除它们?

我可以获得数百万sed个命令,但这需要很长时间才能列出我们拥有的所有非ASCII字符。或者开始在python中解析它。但我希望我能做到一些技巧。

6 个答案:

答案 0 :(得分:5)

这是对Unicode字符的粗略抨击:

text="/My\ Folders/My\ r\303\266m/"
text="echo \$\'"$(echo "$text"|sed -e 's|\\|\\\\|g')"\'"
# the argument to the echo must not be quoted or escaped-quoted in the next step
text=$(eval "echo $(eval "$text")")
read text < <(echo "$text")
echo "$text"

这使用了Bash的$'string'引用功能。

输出“/ My Folders /Myröm/".

从Bash 4.4开始,它就像:

一样简单
text="/My Folders/My r\303\266m/"
echo "${text@E}"

这使用了名为parameter transformation的Bash的新功能。 E运算符会将参数视为其内容位于$'string'内,其中反斜杠转义序列(在本例中为八进制值)进行评估。

答案 1 :(得分:2)

目前尚不清楚究竟使用了什么类型的转义。八进制字符代码是C,但C不会逃避空间。空间转义在shell中使用,但它不使用八进制字符转义。

使用命令printf %b $escaped可以撤消接近C风格转义的内容。 (文档说八进制转义以\0开头,但GNU printf似乎并不需要这样做。)另一个答案提到read来取消转义shell转义,尽管如果空间是唯一的转义不是由printf %b处理,然后使用sed处理该情况可能会更好。

答案 2 :(得分:1)

最后我使用了这样的东西:

cat file | sed 's/%/%%/g' | while read -r line ; do printf "${line}\n" ; done | sed 's/\\ / /g'

其中一些文件中有%,这是一个printf特殊字符,所以我不得不“加倍”以便它会被转义并直接通过。 -r中的read会停止读取\,但读取不会将"\ "转换为" ",因此我需要最终sed }。

答案 3 :(得分:1)

使用printf解决utf-8文本问题。使用read来处理空格(\ )

像这样:

$ text='/My\ Folders/My\ r\303\266m/'
$ IFS='' read t < <(printf "$text")
$ echo "$t"
/My Folders/My röm/

答案 4 :(得分:0)

内置的“读取”功能将处理部分内容 问题:

$ echo "with\ spaces" | while read r; do echo $r; done
with spaces

答案 5 :(得分:0)

将文件(逐行)传递给以下perl脚本。

#!/usr/bin/per

sub encode {
    $String = $_[0];
    $_ = $String;
    while(/(\\[0-9]+|.)/g) {
        $Match = $1;

        if ($Match =~ /\\([0-9]+)/) {
            $Code = oct(0 + $1);
            $Char = ((($Code >= 32) && ($Code  160))
                ? chr($Code)
                : sprintf("\\x{%X}", $Code);
            printf("%s", $Char);
        } else {
            print "$Match";
        }
    }

    print "\n";
}

while ($#ARGV >= 0) {
    $File = shift();
    open(my $F, ") {
        $String =~ s/\\ / /g;
        &encode($Line);
    }
}

像这样:

$ ./PerlEncode.pl Test.txt

Test.txt包含:

/My\ Folders/My\ r\303\266m/
/My\ Folders/My\ r\303\266m/
/My\ Folders/My\ r\303\266m/

“$ String = ~s / \ / / g;”这一行将“\”替换为“”,子编码解析那些unicode char。

希望这个帮助