[分享] 搜尋並取代 某些文件裡面的 某個字串

看板Linux作者 (WeCan)時間16年前 (2009/10/21 20:09), 編輯推噓1(100)
留言1則, 1人參與, 最新討論串1/1
http://liwecan.pixnet.net/blog/post/29606145 == 結論的好方法 == 情境 ex1:將資料夾內 case01.conf ~ case99.conf 裡的 senor 錯字改成 sensor find *.conf | xargs -i sed -i 's/senor/sensor/g' {} find *.conf 會找資料夾內的 .conf 檔, 即情境中的 case01.conf ~ case99.conf,輸出為 99 行; | 是 pipe 指令,能將前者的 standard output, 作為後者的 standard input 繼續處理; (這裡有兩個 point,一是前一個指令的 standard error 會被忽略, 二是後一個指令必需是處理 standard input 的指令) xargs 的目的,是用來將所得的結果參數化, 即我們會將前者的 standard output,當作接下來指令的某個參數。 其中,透過 xargs -i {}, 我們可以將前者 n行輸出的每一行,視為一次輸出, 將其擺至 {} 的位置,而得到 n 次輸入執行 n 遍。 (若不使用 xargs -i {},則會把前面 n行的 output 一次全丟給後者) 也就是說 find *.conf | xargs -i sed -i 's/senor/sensor/g' {} 至此會等同於 sed 's/senor/sensor/g' case01.conf sed 's/senor/sensor/g' case02.conf … sed 's/senor/sensor/g' case99.conf 而 sed 的格式是 sed 'command' filename, command 跟 regular expression 有關, 總之,這個例子的意思是, 尋找 filename 檔案中的所有 senor 字串,並取代為 sensor 字串。 情境 ex2:1test1、1test2 … 24test5、24test6 內, 有些字串是 2.6.16,有些是 2a6b16, 欲將 2.6.16 改為 2.6.28 find *test* | xargs -i sed -i 's/2\.6\.16/2\.6\.28/g' {} ex2 的寫法在底下對 vim 的討論有詳細的解釋, == 對單一檔案的解法 == 假設要將 filename 檔案裡的 2009 改成 2010 vim 解法 (後面有詳細的討論,與不知如何解的問題) vim -c '1,$s/2009/2010/g' -c ':wq' filename 或是 vim 檔案後,直接按 : 輸入 1,$s/2009/2010/g 的指令。 sed 解法 (速度快,效果好) sed -i 's/2009/2010/g' file 有新版的 GNU sed 即可用上面的解法, 舊版的可能要 sed 's/2009/2010/g' oldfile > tmpfile; mv tmpfile oldfile perl 解法 (我不懂 perl,還不會讓其搜尋檔案並操作) 1. 建 xxx.pl 檔,寫一行指令, 2. perl -pi -e "s/2009/2010/g" filename 3. chmod 755 xxx.pl 使其可執行後, 4. 下 ./xxx.pl 執行 == 舊的 vim 的討論 == 目的: 把 fullset-k26.mak 裡的 2.6.16 全部取代成 2.6.28 指令: vim -c ':1,$s/2\.6\.16/2\.6\.28/g' fullset-k26.mak == vim 的 解釋 == vim -c command file 這裡有兩個部份要注意, 一個是 "vim -c command file" 整段是 command line 的命令, 有些特殊字元在 command line 有別的意義, 另一個是 "command" 本身是要傳給 vim 的命令, 要符合 regular expression 的用法。 因為 command line 中, $ 會被視為呼叫變數, 所以需用 \$ 或是 '$' 來表示 $ 是傳給 vim 的 regular expression (在 reqular expression 中, $ 代表 檔尾 or 行尾, 例如 1,$s/x$/l,第一個$是檔尾,第二個$是行尾) 在此是整串 command 都用 ' ' 括住比較方便 (因為後面還有 . 要注意) 在regular expression的 . 代表非斷行的任意字元 所以為了確保不會有 2a6b28 被取代掉, 所以在 vim 的 command 中要用 \. 來表示是 2.6 而非 2a6 之類的任意字元 而在 command line 中,應該用 \\. 或是 '\.' 代表要傳 \. 給 vim (如果是 \.,會把 \ 忽略認為要傳 . 給 vim,vim 會認為 . 代表任意字元 所以是 \\. ,認為要傳 \. 給 vim,讓 vim 找 . 這個字元) 也就是上述的命令等同於 vim -c :1,\$s/2\\.6\\.16/2\\.6\\.28/g fullset-k26.mak 不過,還是用括號括比較方便 也就是一開頭的 vim -c ':1,$/2\.6\.16/2\.6\.28/g' fullset-k26.mak 然後,不再接一個 -c ':wq' 的指令, 他會把檔案開啟來,並把 2.6.16 取代成 2.6.28 後,仍未存檔, 好處是可以檢查無誤後再存檔。 == vim 的 問題 == 與 find *.conf | xargs -i {} 合在一起用時,如: find *.conf | xargs -i vim -c '1,$s/senor/sensor/g' -c ':wq' {} 最後會當掉。 -- -- -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 60.250.190.7

10/25 04:46, , 1F
感謝~ 連兩篇分享的內容面都很實用,值得一看~
10/25 04:46, 1F
文章代碼(AID): #1AtldtLL (Linux)