簡體   English   中英

如何在bash中反轉轉義反斜杠編碼,如“\\”和“\\ 303 \\ 266”?

[英]How do I reverse escape backslash encodings like “\ ” and “\303\266” in bash?

我有一個腳本,記錄UTF8編碼名稱的文件。 但是,腳本的編碼/環境設置不正確,它只是重新編碼原始字節。 我現在在文件中有很多行,如下所示:

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

因此,文件名中有空格,其中包含\\和UTF8編碼的內容,如\\303\\266 (即ö )。 我想反轉這種編碼? 是否有一些簡單的bash命令行命令可以鏈接在一起刪除它們?

我可以獲得數百萬個sed命令,但是要花費很長時間才能列出我們擁有的所有非ASCII字符。 或者開始在python中解析它。 但我希望我能做到一些技巧。

這是對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}"

這使用了Bash的一個新功能,稱為參數轉換 E運算符使得參數被視為其內容在$'string'中,其中反斜杠轉義序列(在本例中為八進制值)被計算。

目前尚不清楚究竟使用了什么類型的轉義。 八進制字符代碼是C,但C不會逃避空間。 空間轉義在shell中使用,但它不使用八進制字符轉義。

使用命令printf %b $escaped可以撤消接近C風格轉義的內容。 (文檔說八進制轉義以\\0開頭,但GNU printf似乎並不需要這樣做。)另一個答案提到read unescaping shell轉義,盡管如果空間是唯一一個不由printf %b處理的那么使用sed處理這種情況可能會更好。

最后我使用了這樣的東西:

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

有些文件中含有% ,這是一個printf特殊字符,所以我不得不“加倍”,以便它可以被轉義並直接通過。 -rread停止讀取逃避\\的讀取但是不轉"\\ "" " ,所以我需要最終sed

使用printf解決utf-8文本的問題。 使用read來處理空格(\\ )

像這樣:

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

內置的“讀取”功能將處理部分問題:

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

將文件(逐行)傳遞給以下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。

希望這有幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM