2016-07-25 254 views
1

我們有一些文件,其中包含一些以十進制(!)ascii值包含在cid(#)中的字符作爲例如字符。 (cid:104)h。字符串hello因此表示爲(cid:104)(cid:101)(cid:108)(cid:108)(cid:111)使用sed替代使用ascii字符的值

我該如何用sed替換相應的ascii字符?

下面是一個例子文件:

$ cat input.txt 
first line 
pre (cid:104)(cid:101)(cid:108)(cid:108)(cid:111) post 
last line 

我試過到目前爲止是:

$ x="(cid:104)(cid:101)(cid:108)(cid:108)(cid:111)" 
$ echo $x | sed 's/(cid:\([^\)]*\))/\1/g' 
104101108108111 

但凌晨所需要的輸出爲hello

$ cat output.txt 
first line 
pre hello post 
last line 

我m試圖在sed中使用printf。但不能找出如何反向引用\1傳遞給printf

sed 's/(cid:\([^\)]*\))/'`printf "\x$(printf %x \1)"`'/g' 
+1

給你更新的問題,什麼是確切的,所需的輸出?請注意,從一開始就提供[mcve]很重要,因爲您的更新會使我們當前的答案無效。 – fedorqui

+0

您可能需要解釋爲什麼'使用sed'是必需的。這比使用更適合的工具(比如awk或perl)要困難得多... –

回答

2
$ cat input.txt 
first line 
pre (cid:104)(cid:101)(cid:108)(cid:108)(cid:111) post 
last line 

$ perl -pe 's/\(cid:(\d+)\)/chr($1)/ge' input.txt > output.txt 
$ cat output.txt 
first line 
pre hello post 
last line 

感謝@ 123建議使用chr($1)而不是sprintf "%c", $1。見chr的文檔

參考:Integer ASCII value to character in BASH using printf

+0

在我們的特殊情況下,還有「正常」字符。即不是所有的字符都表示爲「(cid:#)」,只有其中的一些。我編輯我的原始問題以顯示示例文件 – wolfrevo

+0

您是否也可以明確地發佈您希望輸出文件與樣本輸入文件一起查看的方式?我將相應地編輯答案或刪除 – Sundeep

+1

您可以使用'chr'而不是'sprintf',即'perl -pe's/\(cid:(\ d +)\)/ chr($ 1)/ ge'' – 123

0

使用%c您可以將ASCII代碼轉換成它對應的字符:

$ awk 'BEGIN {printf "%c", 104}' 
h 

因此,它是從(cid:XX)中提取數字的問題。此我做由FS設置爲(並通過字段循環:

awk -v FS='(' '{for (i=2; i<=NF; i++) { 
        r=gensub(/cid:([0-9]+)\)/, "\\1", "g", $i); 
        printf "%c", r+0 
        } 
       }' file 

這使用gensub()和訪問作爲GNU awk: accessing captured groups in replacement text描述的捕捉的基團。因此依賴於GNU awk。

了給定的輸入返回:

$ awk -v FS='(' '{for (i=2; i<=NF; i++) {r=gensub(/cid:([0-9]+)\)/, "\\1", "g", $i); printf "%c", r+0}}' file 
hello