與 r 字元的兩次交鋒

2021-07-12 06:16:22 字數 2373 閱讀 9701

眾所周知,不同的作業系統中,對文字中換行的表示是不同的,在 windows 中用\r\n表示,在 linux 中用\n表示,而在 mac os 中用\r表示。對於像筆者這種以 windows 作為開發環境,linux 作為執行環境的程式設計師來說,經常會不可避免地碰到由換行符不一致而引起到奇怪問題,下面就回溯一下我曾遇到並解決的兩個相關的問題,希望能給讀者來一點啟發。

這是同事遇到的問題,其當時在開發乙個 shell 指令碼,需要乙個從檔案中查詢關鍵字的功能,比如檔案名叫data.txt,要查詢到關鍵字是warn,很容易寫出這樣的命令:

grep warn data.txt
假如檔案的內容是:

warn: wrong

info: good

warn: not good

那麼該命令因該返回兩行:

warn: wrong

warn: not good

到這裡,一切都正常,但是這位同事不滿足於只將結果列印到標準輸出,而是要用乙個變數儲存,以便後續的操作,於是寫下了這樣兩行指令碼:

result=$(

grep

warn data.txt)

echo $result

這時奇怪的事發生了,執行這個指令碼得到的結果是:

_warn: not good  # 注意 'warn' 前面有乙個空格,為了醒目,用 '_' 表示
相信讀者已經猜到,導致這個現象的原因,就是\r字元。下面解釋一下原因。

這個檔案的出處現已無從考證,但其中每行都是以\r\n結束, 推測應該是從 windows 平台拷貝過來的。但是在 linux 中,只有\n被作為換行符,其前面的\r字元將被視為普通的文字內容處理,所以grep命令返回到結果應該為:

warn: wrong\r

warn: not good\r

在向螢幕列印這段內容時,\r字元會被轉義為回車符,其作用是將游標即下乙個字元的輸出位置移動到本行行首(windows 上的\r\n可以理解為先將輸出位置移動到行首,再用\n移動到下一行),但由於\r後面再無其它字元,所以對使用者來說,僅游標位置的移動是感知不到的。

但在指令碼中,情況有了些許的變化——grep的結果不直接列印,而是先賦值給變數,再列印變數。區別在於指令碼中會將result中的內容按行分割,再依次傳給echo,實際執行的命令為:

echo warn: wrong\r warn: not good\r
上面已經說過,\r字元會使游標回到行首,所以第乙個\r字元前的內容會被後面的內容覆蓋,這便是問題所在。

其實只要將輸出命令寫成:

echo

"$result"

而不是

echo

$result

就不會有這個問題,因為雙引號中的內容會被當作純粹的字串處理,不做轉義,實際的命令為:

echo

"warn: wrong\r

warn: not good\r"

內容分為兩行列印,和直接用grep輸出的結果一樣。

這次到問題出現在另一同事的指令碼中,其內容只有兩行編譯命令,被打在乙個 rar 包中發給我。兩行命令的內容都查不多,但命令的內容無關緊要,假設為:

g++

-wall source.cpp -i

...-l

...-o source -l***

其中的 *** 是乙個本專案的動態庫。我直接在本地執行該指令碼,但鏈結失敗,報 『***』 庫找不到。

第一反應當然是庫所在的目錄沒有被加到動態庫的搜尋路徑中,但檢查了一遍發現不是。又懷疑命令寫的有問題、動態庫檔案沒有讀許可權、檔名寫錯,但都驗證通過了。折磨了有半個小時,突然靈光一現,用dos2unix命令轉換了一下編譯指令碼,隨即編譯通過。

原因很簡單,這個指令碼中每一行的末尾都有乙個\r,恰好跟在 『***』 後面,變成了 『***\r』,鏈結時實際查詢的是 『***\r』 檔案,當然找不到了。但由於列印到螢幕上的內容是一樣到,所以很難發現。

兩次請求與三次握手

在使用 時。第一次訪問伺服器時,顯示request建立銷毀了三次,session建立銷毀了三次,這是由於網路傳輸是基與http協議的,而http協議在在第一次訪問伺服器時進行的是三次握手。所以顯示三次。在於伺服器建立鏈結後,關閉瀏覽器,重新開啟頁面會產生兩次request的建立與銷毀,一次sessi...

一次fork與兩次fork的區別

在講一次fork和兩次fork之前,有必要先來簡單講解一下wait的作用 1 阻塞當前程序 2 獲得子程序退出的相關資訊 殭屍程序 子程序不返回,父程序後邊的內容就沒法執行。注 wait函式只能在有子程序的父程序中呼叫。我們使用fork 函式建立乙個子程序出來往往是為了父子程序能夠同時執行兩段 如果...

listview 重新整理兩次的問題

遇到個奇怪的現象,listview每次都重新整理兩次,在網上查詢了好久,無果,後來看見一片部落格中提到 的getview會重複執行多次,這次因為布局比較複雜,所以在測試的時候去斷點跟蹤,發現同一條資料不斷的重複執行 listview是根據布局來確定當錢重新整理的item並確定是否重新整理完畢,我按照...