Subscribed unsubscribe Subscribe Subscribe

Mac の sed で置換できない。

Mac

症状

find /usr/local/mrtg | xargs grep -l WorkDir | sed -i 's|/usr/local/mrtg/data|/Library/WebServer/Documents/mrtg|'
sed: -i may not be used with stdin

ん?
 

オプションを e に換える。

find /usr/local/mrtg | xargs grep -l WorkDir | sed -e 's|/usr/local/mrtg/data|/Library/WebServer/Documents/mrtg|'
file_path1
file_path2
file_path3
...

あれ?grep の結果しか表示されない。
 

神様サイトを発見。
sedでファイルを上書き保存
i オプションを使わない形で書き換える。

find /usr/local/mrtg/*.cfg | while read file; do cat $file | (rm $file; sed -e 's|/usr/local/mrtg/data|/Library/WebServer/Documents/mrtg|'>$file);done

 

そして、もう1度冷静に考えてみる。

sed コマンドの前に、xargs がはいっていないことが i オプション使えなかったことの原因かな...。
それとも -l オプションが行けなかったかな。
 

解説らしきもの

stackoverflow には、神様が住んでいます。

The problem is that Mac OS X uses the BSD version of sed, which treats the -i option slightly differently...

http://stackoverflow.com/questions/21242932/sed-i-may-not-be-used-with-stdin-on-mac-os-x

 

その他、新しく覚えたこと

sed の区切り文字

s の後ろに '/' ではなく別の文字を指定すると、それが区切り文字になるようで、'|' とかでもいけるみたいです。
フィルタを使用した文字列操作 1 - UNIX & Linux コマンド・シェルスクリプト リファレンス

-i オプションの後ろにファイル名をいれるとバックアップを作ってくれる。

sed -iオプション - None.

備忘録

例えば、中括弧の中身だけを抜き出す場合、

sed -e "s/.*¥[¥(.*¥)¥].*/¥1/"

中括弧の中身を抜き出し、さらに先頭にファイル名を記載する場合、

 find /usr/local/mrtg/*.cfg | while read file; do grep -s Target $file | (name=${file##*/};name=${name%.*};sed -e "s/.*\[\(.*\)\].*/${name}\1/");done

中括弧で並列処理か。

シングルクオートだと動かないらしい。
foguera blog: sedの変数参照にハマった

何故なのか。

iMac:~ domo$ grep -s WorkDir /usr/local/mrtg/localhost.cfg | sed -e 's|WorkDir:[ ]+\(/.*\)|\1|'
WorkDir:         /Library/WebServer/Documents/mrtg/localhost.cfg/
iMac:~ domo$ grep -s WorkDir /usr/local/mrtg/localhost.cfg | sed -e 's|WorkDir:.*\(/.*\)|\1|'
/
iMac:~ domo$ grep -s WorkDir /usr/local/mrtg/localhost.cfg | sed -e 's|WorkDir:[ ]*\(/.*\)|\1|'
/Library/WebServer/Documents/mrtg/localhost.cfg/
Remove all ads