== 結論的好方法 ==
情境 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' {}
最後會當掉。
--