$(...):將命令輸出作為參數# 1. 確認匹配範圍
grep -rn "old_string" /target/dir
# 2. 僅列出需修改的檔案
grep -rl "old_string" /target/dir
# 3. 批量替換(備份建議先 cp -r)
sed -i "s/old_string/new_string/g" $(grep -rl "old_string" /target/dir)
# 4. 驗證結果
grep -rn "new_string" /target/dir
專案中大量靜態頁面包含硬編碼舊域名 https://yyy.xxx.edu.cn、https://www.asdf.net、https://asdf.net,需批量移除域名部分,保留相對路徑。
# 目錄結構
.
├── a/
│ └── target1.txt
├── target2.txt
└── target.txt
# 1. 替換第一個域名
sed -i 's|https://yyy\.xxx\.edu\.cn||g' $(grep -rl 'https://yyy\.xxx\.edu\.cn' *)
# 2. 替換第二個域名
sed -i 's|https://www\.asdf\.net||g' $(grep -rl 'https://www\.asdf\.net' *)
# 3. 替換第三個域名
sed -i 's|https://asdf\.net||g' $(grep -rl 'https://asdf\.net' *)
# 4. 驗證
cat target.txt
# 輸出應變為相對路徑:href="/scholar/xxx.html"
| 參數 | 作用 |
|---|---|
-r | 遞歸子目錄 |
-l | 只輸出檔案名(配合 sed -i 必用) |
-n | 顯示行號 |
-i | 忽略大小寫 |
-w | 整詞匹配 |
-Z | 以 null 字符分隔輸出(配合 xargs -0 處理特殊檔名) |
sed -i 's/old/new/g' file # 全行所有匹配替換
sed -i 's/old/new/' file # 每行僅首個匹配
sed -i '2,5s/old/new/g' file # 僅第 2-5 行
sed -i '/pattern/s/old/new/g' file # 僅匹配 pattern 的行
sed -i 's|/|/|g' file # 使用 | 作為分隔符,避免路徑轉義
.\*[]^$()+?{| 需轉義s|old|new|、s@old@new@、s#old#new#& 會被解釋為「整個匹配串」,需寫 \&當匹配檔案過多導致「參數列表過長」錯誤:
# 安全模式:null 分隔 + xargs
grep -rlZ "pattern" /dir | xargs -0 sed -i 's/pattern/replacement/g'
# 並行加速
grep -rl "pattern" /dir | xargs -P4 -I{} sed -i 's/pattern/replacement/g' {}
# 安裝
cargo install ripgrep sd
# 查找
rg "pattern" /dir
# 替換(sd 语法更簡潔,無需轉義正則)
sd "pattern" "replacement" $(rg -l "pattern" /dir)
cp -r /target /target.bak 完整備份grep -rn 確認匹配範圍sed -n 's/old/new/gp' file (僅輸出不寫入)grep -rn "new" 驗證git diff 審查變更