2012-07-09 43 views

回答

288
cd /path/to/your/folder 
sed -i 's/foo/bar/g' * 

「foo」的出現將被替換爲「bar」。

+6

如果字符串中有空格或特殊字符,這似乎不適用於我。任何想法,爲什麼這可能,或者我需要逃避他們如何?謝謝! – 2014-08-06 17:54:20

+8

至少對於我的'sed'版本,'-i'需要一個後面的字符串,它被附加到舊的文件名中。因此,'sed -i .bak's/foo/bar/g'* .xx'將所有'.xx'文件移動到等效的'.xx.bak'名稱,然後用foo生成'.xx'文件→條代替。 – Anaphory 2014-10-04 22:35:22

+8

如果有人想要尋找更多的選擇,有一個關於unix堆棧交換的答案,它涵蓋了更多的用例站點http://unix.stackexchange.com/a/112024/13488 – Reddy 2015-05-22 09:40:02

20

這爲我工作:

find ./ -type f -exec sed -i 's/string1/string2/' {} \; 

Howerver,這並不:sed -i 's/string1/string2/g' *。也許「foo」並不意味着是string1和「bar」而不是string2。

+1

這是因爲sed以不同的方式處理通配符* [abc] *表示集合中的任意數量的字符{a,b ,c}。[a-z0-9] *的作用類似於通配符*。 – thepiercingarrow 2016-03-17 00:19:03

84

@ kev的回答很好,但隻影響直接目錄中的文件。下面的示例使用grep遞歸查找文件。它每次都適合我。

grep -rli 'old-word' * | xargs [email protected] sed -i 's/old-word/new-word/g' @ 
+9

這對我不起作用,但是這樣做: 'grep --include = {* .php,*。html,* .js } -rnl'./'-e「old-word」| xargs -i @ sed -i's/old-word/new-word/g'@' – Dennis 2014-03-05 22:20:16

+3

@pymarco你能解釋一下這個命令嗎?我不知道爲什麼你必須使用xargs而不是'''之後使用sed,還有,爲什麼'-i'在xargs命令中?我在手冊中讀過它,而不應該使用'-I'。用'@'作爲模式開始和結束的分隔符? – 2015-11-09 14:57:29

+0

'sed沒有輸入文件',不能正常工作 – 2016-08-29 13:46:16

130

與Kaspar的答案類似,但用g標誌替換一行中的所有事件。

find ./ -type f -exec sed -i 's/string1/string2/g' {} \; 

對於全球不區分大小寫:

find ./ -type f -exec sed -i 's/string1/string2/gI' {} \; 
+10

如果你在OSX上並且你的模式可能包含點並且你想要就地替換(沒有備份文件),你應該使用' LC_ALL = C find ./ -type f -exec sed -i''-e's/proc.priv/priv/g'{} \;'(參見[這篇文章])(http://stackoverflow.com/questions/19456518/invalid-command-code-though-escaping-periods-using-sed)和[this one](http://stackoverflow.com/questions/19242275/re-error-illegal-byte-sequence-on-mac -os-x)) – Sheljohn 2015-08-13 15:01:19

+1

這對我來說絕對有效,因爲它可以使用-name「* .js」' – 2016-02-17 11:30:03

+0

進行過濾詳細選項將很酷,但是您可以重新grep以查看是否進行了更改。注意:對於通配符,嘗試使用'-name'* .php'',並且grep對於遞歸和通配符不好,您需要使用-r – 2017-02-23 18:41:35

7

如果你有文件的列表,你可以使用

replace "old_string" "new_string" -- file_name1 file_name2 file_name3 

如果你把所有的文件,你可以使用

replace "old_string" "new_string" -- * 

如果您有擴展名的文件的列表,你可以使用

replace "old_string" "new_string" -- *.extension 
+2

其實,」--file「應該是」 - 「,在至少在我的版本中 – simpleuser 2014-10-07 23:34:30

+2

此實用程序分佈在MySQL包中。 – 2014-10-14 16:00:11

+2

雖然我想感謝解決方案,它沒有引用常規的行是正則表達式。 – 2014-10-14 16:05:41

17

要替換多個文件中的一個字符串,你可以使用:

grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g' 

例如

grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g' 

Source blog

1

流編輯器,與-i開關,這需要作爲參數結尾的備份文件調用並修改多個文件「就地」。所以

sed -i.bak 's/foo/bar/g' * 

取代foo在此文件夾中的所有文件bar,但不會下降到子文件夾。然而,這將爲您的目錄中的每個文件生成一個新的.bak文件。 要遞歸執行此目錄及其所有子目錄中的所有文件,您需要助手(如find)來遍歷目錄樹。

find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' * 

find讓你上的哪些文件來修改進一步的限制,通過指定如find ./ -name '*.php' -or -name '*.html' -print0進一步論證,如果必要的。


注:GNU sed不需要文件結尾,sed -i 's/foo/bar/g' *會的工作,爲好; FreeBSD sed要求擴展名,但允許在一個空格之間,所以sed -i .bak s/foo/bar/g *工作。

2

腳本multiedit命令

multiedit [-n PATTERN] OLDSTRING NEWSTRING 

從卡斯帕的答案我做了一個bash腳本接受命令行參數和可選限制模式匹配的文件名。保存在你的$ PATH中並生成可執行文件,然後使用上面的命令。

這裏的腳本:

#!/bin/bash 
_help="\n 
Replace OLDSTRING with NEWSTRING recursively starting from current directory\n 
multiedit [-n PATTERN] OLDSTRING NEWSTRING\n 

[-n PATTERN] option limits to filenames matching PATTERN\n 
Note: backslash escape special characters\n 
Note: enclose STRINGS with spaces in double quotes\n 
Example to limit the edit to python files:\n 
multiedit -n \*.py \"OLD STRING\" NEWSTRING\n" 

# ensure correct number of arguments, otherwise display help... 
if [ $# -lt 2 ] || [ $# -gt 4 ]; then echo -e $_help ; exit ; fi 
if [ $1 == "-n" ]; then # if -n option is given: 
     # replace OLDSTRING with NEWSTRING recursively in files matching PATTERN 
     find ./ -type f -name "$2" -exec sed -i "s/$3/$4/g" {} \; 
else 
     # replace OLDSTRING with NEWSTRING recursively in all files 
     find ./ -type f -exec sed -i "s/$1/$2/" {} \; 
fi 
13

要替換文件中的路徑(避免轉義字符),你可以使用下面的命令:

sed -i '[email protected][email protected][email protected]' 

@符號意味着所有的特殊字符應該在以下字符串中被忽略。

+0

正是我在尋找所有其他答案。也就是說,如何處理特殊字符,例如當改變一個字符串是一個路徑時。謝謝。在其他答案中看起來像是一個大的疏忽。 – inspirednz 2018-02-28 05:54:52

4

「你也可以使用find和sed,但我發現這個小的perl線工作得很好。

perl -pi -w -e 's/search/replace/g;' *.php 
  • -e手段執行下面的代碼行。
  • -i手段編輯就地
  • -w寫警告
  • -p環

「(從http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php中提取)

我最好的結果來自用perl和grep(以確保文件具有搜索表達式)

perl -pi -w -e 's/search/replace/g;' $(grep -rl 'search') 
17

現在已經列出了一些標準答案,這樣。通常,您可以使用查找遞歸列出文件,然後使用sedperl執行操作。

對於大多數快速使用,您可能會發現命令rpl更容易記住。這裏是更換(FOO - >吧),遞歸上的所有文件:

rpl -R foo bar .

你可能需要安裝它(apt-get install rpl或類似)。

然而,對於涉及正則表達式和回代艱難的工作,或文件重命名以及搜索和替換,最普遍和強大的工具,我所知道的是repren,一個小的Python腳本,我寫了同時支持一些棘手的重命名和重構任務。您可能更喜歡它的原因是:

  • 支持重命名文件以及搜索和替換文件內容。
  • 在承諾執行搜索和替換之前查看更改。
  • 支持帶後置替換的正則表達式,整個單詞,不區分大小寫和保留大小寫(替換foo - > bar,Foo - > Bar,FOO - > BAR)模式。
  • 可以使用多種替換方式,包括掉換(foo - > bar和bar - > foo)或一組非替換(foo - > bar,f - > x)。

使用它,pip install repren。例如Check the README

+1

哇,repren非常好!剛剛使用它來更改類名稱,方法和變量中的單詞的一部分,同時重命名文件以匹配1000多個C++頭文件和源文件,並且它在第一次使用一個命令時完美運行。謝謝! – 2017-11-01 18:49:37

1

如果文件中包含反斜槓(路徑通常情況下),你可以嘗試這樣的事:

sed -i -- 's,<path1>,<path2>,g' * 

例如:

sed -i -- 's,/foo/bar,/new/foo/bar,g' *.sh (in all shell scripts available) 
0

以下命令可以用來首先搜索的文件和替換文件

找到。 | xargs grep搜索字符串| sed's/search string/new string/g'

例如find。 | xargs grep abc | sed's/abc/xyz/g'

4

我在找到這個問題(和答案)之前編寫了自己的解決方案。 我搜索了「替換」「幾個」和「xml」的不同組合,因爲這是我的應用程序,但沒有找到這個特定的組合。

我的問題:我有包含複雜對象的測試用例數據的spring xml文件。 java源代碼的重構改變了很多類,並且不適用於xml數據文件。爲了保存測試用例數據,我需要更改所有xml文件中的所有類名,分佈在多個目錄中。所有這些都保存了原始xml文件的備份副本(儘管這不是必須的,因爲版本控制會將我保存在這裏)。

我正在尋找find + sed的某種組合,因爲它在其他情況下適用於我,但不能同時進行多次替換。

後來我發現ask ubuntu response,它幫助我建立我的命令行:

find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \; 

它完美地工作(當然,我的情況有六種不同的替代品)。但請注意,它會觸及當前目錄下的所有* .xml文件。因此,如果您對版本控制系統負責,則可能需要首先進行篩選,然後只傳遞給sed那些實際上具有所需字符串的人;像:

find -name "*.xml" -exec grep -e "firstWord" -e "secondWord" -e "thirdWord" {} \; -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \; 
+0

和windows,我只是發現有一種方法可以找到字符串 - 還沒有檢查如何替換它 - 在一個命令中: 'findstr/spin/c:「quéquieresbuscar」* .xml ' 它會很方便。 – manuelvigarcia 2016-06-08 11:07:41

1

爲了維護我個人的英語節點,我寫了一個程序腳本,幫助來替代多個對舊/新字符串,對所有文件的目錄下遞歸。

多對舊/新字符串在哈希映射中進行管理。

可以通過命令行或環境變量設置目錄,地圖在腳本中是硬編碼的,但如果需要,您可以修改要從文件加載的代碼。

由於一些新功能,它需要bash 4.2。

en_standardize.sh:

#! /bin/bash 
# (need bash 4.2+,) 
# 
# Standardize phonetic symbol of English. 
# 
# format: 
# en_standardize.sh [<dir>] 
# 
# params: 
# * dir 
# target dir, optional, 
# if not specified then use environment variable "$node_dir_en", 
# if both not provided, then will not execute, 
# * 
# 

paramCount=$# 

# figure target dir, 
if [ $paramCount -ge 1 ]; then # dir specified 
    echo -e "dir specified (in command):\n\t$1\n" 
    targetDir=$1 
elif [[ -v node_dir_en ]]; then # environable set, 
    echo -e "dir specified (in environment vairable):\n\t$node_dir_en\n" 
    targetDir=$node_dir_en 
else # environable not set, 
    echo "dir not specified, won't execute" 
    exit 
fi 

# check whether dir exists, 
if [ -d $targetDir ]; then 
    cd $targetDir 
else 
    echo -e "invalid dir location:\n\t$targetDir\n" 
    exit 
fi 

# initial map, 
declare -A itemMap 
itemMap=(["ɪ"]="i" ["ː"]=":" ["ɜ"]="ə" ["ɒ"]="ɔ" ["ʊ"]="u" ["ɛ"]="e") 

# print item maps, 
echo 'maps:' 
for key in "${!itemMap[@]}"; do 
    echo -e "\t$key\t->\t${itemMap[$key]}" 
done 
echo -e '\n' 

# do replace, 
for key in "${!itemMap[@]}"; do 
    grep -rli "$key" * | xargs [email protected] sed -i "s/$key/${itemMap[$key]}/g" @ 
done 

echo -e "\nDone." 
exit 
0

我給用於在python源固定一個共同認領錯誤的例子。

您可以嘗試grep/sed方法。這裏是一個與GNU工程sed和不會打破一個混帳回購協議:

$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \ 
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {} 

或者greptile :)

$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' . 

我只是測試的第一個腳本,您可以使用,第二個應該工作以及。注意轉義字符,我認爲在大多數情況下應該更容易使用greptile。當然,你可以用sed做很多有趣的事情,爲此,最好將它與xargs一起使用。

6

「foo」的第一行出現將替換爲「bar」。你可以使用第二行來檢查。

grep -rl 'foo' . | xargs sed -i 's/foo/bar/g' 
grep 'foo' -r * | awk -F: {'print $1'} | sort -n | uniq -c 
+6

爲什麼你鏈接到你的博客?它包含與您的答案完全相同的文本。 – DavidPostill 2017-05-01 21:07:31

+1

我喜歡'grep -rl'foo'。 | xargs sed -i's/foo/bar/g'' – Prachi 2017-07-11 21:04:36

0

我發現從另一個崗位這一項(不記得是哪),雖然不是最優雅的,它的簡單,作爲一個新手的Linux用戶給我任何麻煩

for i in *old_str* ; do mv -v "$i" "${i/\old_str/new_str}" ; done 

,如果你有空格或其他特殊字符使用\

for i in *old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done 

在子目錄字符串使用**

for i in *\*old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done 
-4

$替換 「要從」 「」 - `找到/路徑/到/文件夾型F`

(更換 - MySQL數據庫系統的字符串替換實用工具)

1

真的跛腳,但我無法得到任何關於sed命令的工作的權利上OSX,所以我做了這個愚蠢的事情,而不是:

:%s/foo/bar/g 
:wn 

^- 這三行復制到剪貼板中我的(是的,包括終止換行符),那麼:

vi *

並按住command-v直到它說沒有剩下的文件。

阿呆... ...哈克有效...

2

如果你的字符串中有斜槓(/),你可以改變分隔符「+」。

find . -type f -exec sed -i 's+http://example.com+https://example.com+g' {} + 

該命令將在當前目錄中遞歸運行。

+0

謝謝!幫助將'../ domain.com'的引用加載到'domain.com' – 2018-03-08 17:29:28

相關問題