iT邦幫忙

0

Ubuntu中用shell取代特定資料夾內全部檔案(含子資料夾)內特定字串

舜~ 2019-12-11 15:08:071105 瀏覽

如提,各位大大午安

想問一下,小弟對Linux不熟,檔案在文字介面Ubuntu上,

  1. 使用指令取代特定資料夾內全部檔案(含子資料夾)內容中符合regex的文字,要怎麼實現??
  2. 如果要處理含有(?!...)/(?<!...)/$1的regex,sed指令要如何下??或其他替代方式

regex

要被取代的字串(regex) 取代成新字串
ovesc_sp_2(?!_debug)(?!_test) ovesc_sp_2_debug
(?<!233)([/'"])sp([/'"]) $1sp_debug$2

測試檔

/sp/
/sp_debug/
'sp'
"sp"
'233/sp'
ovesc_sp_2_debug
define('DB_NAME', 'ovesc_sp_2');

預期結果

/sp_debug/
/sp_debug/
'sp_debug'
"sp_debug"
'233/sp'
ovesc_sp_2_debug
define('DB_NAME', 'ovesc_sp_2_debug');

參考
Linux使用指令來取代檔案內的字串
第十一章、正規表示法與文件格式化處理

測試:
echo '"sp"' | sed -r 's/([/''"])sp([/''"])/$1sp_debug$2/g'
預期是 "sp_debug"
結果是 $1sp_debug$2

echo 'ovesc_sp_2___' | sed -r 's/ovesc_sp_2(?!debug)/ovesc_sp_2_debug/'
預期是 ovesc_sp_2_debug
__
結果是 sed: -e 表示式 #1,字元 40: 不適用的前置常規表示式

sed -i -r 's/\/ovesc_sp_2(?!_debug)\//ovesc_sp_2_debug/' $(grep -rl 'ovesc_sp')
結果是 sed: -e 表示式 #1,字元 44: 不適用的前置常規表示式

看更多先前的討論...收起先前的討論...
舜~ iT邦高手 1 級 ‧ 2019-12-11 15:19:45 檢舉
[參考](http://linux.vbird.org/linux_basic/0330regularex.php#sed_replace)
的語法測試 echo '"sp"' | sed 's/(?<!233)([/'"])sp([/'"])/$1sp_debug$2/g'
會出現 -bash: syntax error near unexpected token `)'
預期要出現 "sp_debug"
froce iT邦大師 1 級 ‧ 2019-12-11 15:52:46 檢舉
建議用python寫會比較輕鬆好懂,shell script方便,但是不好閱讀
沒特別測試 大致上應該可以這樣寫
sed -i 's/\/ovesc_sp_2(?!_debug)\//ovesc_sp_2_debug/' $(grep -rl '/ovesc_sp_2(?!_debug)/')
舜~ iT邦高手 1 級 ‧ 2019-12-11 16:41:49 檢舉
改良了一下
echo '"sp"' | sed -r 's/([/''"])sp([/''"])/$1sp_debug$2/g'
出來是 $1sp_debug$2 ,但預期是 "sp_debug" ...
舜~ iT邦高手 1 級 ‧ 2019-12-11 16:51:21 檢舉
@froce
python沒寫過...
@RRRRRR...
echo 'ovesc_sp_2___' | sed -r 's/\/ovesc_sp_2(?!_debug)\//ovesc_sp_2_debug/'
sed: -e 表示式 #1,字元 44: 不適用的前置常規表示式
想請問下這個的用意是什麼@@
echo 'ovesc_sp_2___'
順便說明下我的寫法是
sed -i 's/搜尋字串(/ovesc_sp_2(?!_debug)/) /替換字串(ovesc_sp_2_debug)' 搜尋包含字串(/ovesc_sp_2(?!_debug)/)並列出檔案名稱
我理解的問題是
將特定目錄(包含子目錄)底下所有檔案內的字串 /ovesc_sp_2(?!_debug)/ 替換成 ovesc_sp_2_debug
還是我誤會了題意?
舜~ iT邦高手 1 級 ‧ 2019-12-11 17:04:40 檢舉
@RRRRRRRR 抱歉讓您誤解了,我想實際寫入檔案前想先測試regex語法是否是有效的,所以才加上echo 'ovesc_sp_2___',預期輸出是ovesc_sp_2_debug___
舜~ iT邦高手 1 級 ‧ 2019-12-11 17:13:55 檢舉
@RRRRRRRR 我建了一個測試檔測試您教的語法,出現
sed: 沒有輸入檔案
能否貼一下測試檔案的內容以及完整指令
舜~ iT邦高手 1 級 ‧ 2019-12-11 17:26:46 檢舉
測試檔
/sp/
/sp_debug/
'sp'
"sp"
'233/sp'
ovesc_sp_2_debug
define('DB_NAME', 'ovesc_sp_2');
舜~ iT邦高手 1 級 ‧ 2019-12-11 17:28:59 檢舉
理想結果是
/sp_debug/
/sp_debug/
'sp_debug'
"sp_debug"
'233/sp'
ovesc_sp_2_debug
define('DB_NAME', 'ovesc_sp_2_debug');
舜~ iT邦高手 1 級 ‧ 2019-12-11 17:35:45 檢舉
指令還在摸索中,不好一次到位就分兩次處理
這個指令 sed -i -r 's/([/''"])sp([/''"])/$1sp_debug$2/g' $(grep -rl 'sp');
結果與預期不同

$1sp_debug$2
/sp_debug/
'sp'
$1sp_debug$2
'233/sp'
ovesc_sp_2_debug
define('DB_NAME', 'ovesc_sp_2');
舜~ iT邦高手 1 級 ‧ 2019-12-11 17:38:43 檢舉
sed -i -r 's/\/ovesc_sp_2(?!_debug)\//ovesc_sp_2_debug/' $(grep -rl 'sp')
結果(我有額外加-r參數)
sed: -e 表示式 #1,字元 44: 不適用的前置常規表示式
你需求的匹配比我想的更複雜QQ ,我只能採用grep -Prl 匹配相關字的檔案 再將 sp 替換成 sp_debug
EX1: 先用grep -E 查找符合以下的檔案
/sp/
'sp'
"sp"
sed -i 's/sp/sp_debug/g' $(grep -Prl "(^/{1}|'|\")sp('|\/|\"$)")

EX2: 只查找匹配 define('DB_NAME', 'ovesc_sp_2'); 排除ovesc_sp_2_debug 的檔案.再將 ovesc_sp_2 替換成 ovesc_sp_2_debug

sed -i 's/ovesc_sp_2/ovesc_sp_2_debug/g ' $(grep -Prl 'ovesc_sp_2(?!_debug)')
如果不符合你的需求只能等其他大大解答了 Orz..

尚未有邦友回答

立即登入回答