2013-05-30 49 views
1

以下this answer here我正在嘗試使用'腳本'命令取消緩衝輸出以便與管道一起使用。但它沒有像我期望的那樣工作。如何在sed中使用管道中'腳本'命令的輸出

我有以下文件:

$ cat test.txt 
first line 
second line 
third line 

現在,當我運行兩個以下兩條命令我預計它們的輸出是一樣的,但它們不是:

$ cat test.txt | sed -n '{s/^\(.*\)$/\^\1\$/;p;}' 
^first line$ 
^second line$ 
^third line$ 

$ script -c "cat test.txt" -q /dev/null | sed -n '{s/^\(.*\)$/\^\1\$/;p;}' 
$first line 
$^second line 
$^third line 

的輸出第一個命令是預期的輸出。第二條命令的輸出如何解釋?

+0

您是否嘗試過其他解決方案? – tuxuday

回答

1

由於script正在模擬將換行符(\n)轉換爲回車/換行序列(\r\n)的終端。 OTOH,sed將回車解釋爲行的一部分,並在其後面插入'$'。然後,當它輸出到終端時,它通過將光標移動到行的開頭並在那裏繼續輸出來解釋回車。

你可以通過管道輸出看到這個到hexdump -C。首先比較catscript輸出:

$ cat test.txt | hexdump -C 
00000000 66 69 72 73 74 20 6c 69 6e 65 0a 73 65 63 6f 6e |first line.secon| 
00000010 64 20 6c 69 6e 65 0a 74 68 69 72 64 20 6c 69 6e |d line.third lin| 
00000020 65 0a            |e.| 
00000022 

$ script -c "cat test.txt" -q /dev/null | hexdump -C | cat 
00000000 66 69 72 73 74 20 6c 69 6e 65 0d 0a 73 65 63 6f |first line..seco| 
00000010 6e 64 20 6c 69 6e 65 0d 0a 74 68 69 72 64 20 6c |nd line..third l| 
00000020 69 6e 65 0d 0a         |ine..| 
00000025 

然後比較輸出通過sed管道:

$ cat test.txt | sed -n 's/^\(.*\)$/\^\1\$/;p;' | hexdump -C 
00000000 5e 66 69 72 73 74 20 6c 69 6e 65 24 0a 5e 73 65 |^first line$.^se| 
00000010 63 6f 6e 64 20 6c 69 6e 65 24 0a 5e 74 68 69 72 |cond line$.^thir| 
00000020 64 20 6c 69 6e 65 24 0a       |d line$.| 
00000028 

$ script -c "cat test.txt" -q /dev/null | sed -n 's/^\(.*\)$/\^\1\$/;p;' | hexdump -C 
00000000 5e 66 69 72 73 74 20 6c 69 6e 65 0d 24 0a 5e 73 |^first line.$.^s| 
00000010 65 63 6f 6e 64 20 6c 69 6e 65 0d 24 0a 5e 74 68 |econd line.$.^th| 
00000020 69 72 64 20 6c 69 6e 65 0d 24 0a     |ird line.$.| 
0000002b 

所以,當script | sed這個輸出到終端:

$first line 
$^second line 
$^third line 

這是發生了什麼:

  1. 「^第一行」是輸出,光標位於行
  2. 「\ r」爲輸出,光標移動到行的開始(列0)
  3. 「$」是輸出結束,覆蓋「^」並將光標移動到第1列
  4. 輸出「\ n」,將光標移動到下一行,但將其保留在第1列中
  5. 從第1列開始輸出「第二行」在那一刻的第0列),光標在行的末尾
  6. 輸出「\ r」,將光標移動到行的開頭(列0)
  7. 「$」是在列0輸出,移動光標到塔1
  8. 「\ n」是輸出,上
移動光標到下一行,但把它留在塔1
  • 如果您仍然想使用script,請刪除\r個字符。就像這樣:

    script -c "cat test.txt" -q /dev/null | sed -n 's/\r//; s/^\(.*\)$/\^\1\$/;p;' 
    

    注意,你仍然會看到在終端上「階梯」的輸出,即使sed的輸出是好的。我不知道爲什麼會發生這種情況,可能script正在修改終端設置。例如,如果通過「cat」輸出輸出,「階梯」效果消失。

  • +0

    我將添加hexdump到我的常規工具集,謝謝! 這個重寫工作: 'script -c「cat test.txt」-q/dev/null | dos2unix | sed -n'{s/^ \(。* \)$/\^\ 1 \ $ /; p;}'' – Joost

    +0

    不客氣:) – spbnick

    +0

    @Joost看到我的答案更新爲另一個解決方案 – spbnick

    0

    這可能會爲你工作:

    script -c"cat test.txt |sed 's/.*/^&$/'" -q /dev/null 
    

    或者更好的是:

    script -c"sed 's/.*/^&$/' test.txt" -q /dev/null 
    

    注:整個script傳遞給腳本