programing

리눅스 명령줄에서 여러 파일의 문자열을 교체하는 방법

sourcetip 2023. 4. 22. 23:07
반응형

리눅스 명령줄에서 여러 파일의 문자열을 교체하는 방법

내의 에 있는 을 더더내 i i i i i in in i i i i i i i i i i i i i i i i a a a로 해야 합니다.ssh서버에 액세스 합니다.★★★★★★★★★★★★★★★★★★★?

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

"foo"는 "bar"로 대체됩니다.

등의 에서는 MacOS BSD와 같은 백업 .-i '.bak'맨페이지

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

Kaspar의 답변과 비슷하지만 한 라인에서 발생한 모든 항목을 g 플래그로 대체합니다.

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

글로벌 대소문자를 구분하지 않는 경우:

find ./ -type f -exec sed -i 's/old_string/new_string/gI' {} \;

@kev의 답변은 좋지만, 바로 앞에 있는 디렉토리의 파일에만 영향을 줍니다.다음 예제에서는 GREP를 사용하여 파일을 반복적으로 검색합니다.매번 효과가 있어요.

grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @

명령어 분류

grep - r : --displays, 각 디렉토리 아래의 모든 파일을 재귀적으로 읽습니다.
grep - l : -- print-with-filength 는 일치하는 행을 인쇄하지 않고 일치하는 각 파일의 이름을 인쇄합니다.
grep - i: --syslog-case.

xargs:STDIN을 인수로 변환합니다.다음 답변에 따릅니다.
xargs -i@ ~명령어는 ~명령어의 특정 위치에서 사용할 인수의 자리 표시자를 포함합니다.@ 기호는 임의의 문자열로 대체할 수 있는 자리 표시자입니다.

sed - i: 백업 없이 파일을 편집한다.
sed s/regexp/replacement/: regexpreplacement가 일치하는 대체 문자열.
sed s/regexp/replacement/g: 글로벌, 첫 번째 일치뿐만 아니라 각 일치에 대한 치환을 수행합니다.

이에 대한 몇 가지 표준 답변이 이미 나와 있습니다.일반적으로 find를 사용하여 파일을 반복적으로 나열한 후 sed 또는 perl을 사용하여 작업을 수행할 수 있습니다.

RPL

대부분의 경우 명령어 rpl이 훨씬 기억하기 쉽다는 것을 알 수 있습니다.

foobar 모로.txt 삭제:

rpl -v foo bar '*.txt' 

의 을 시뮬레이트 .foo.*bar 모로.txt일일: :

rpl --dry-run 'foo.*' bar '**/*.txt'

될 입니다(</FONT CHANGEapt-get install rpl★★★★★★★★★★★★★★★★★★」

응답

그러나 정규 표현식, 백 치환, 파일 이름 변경 및 검색 및 치환과 같은 어려운 작업의 경우, 내가 알고 있는 가장 일반적이고 강력한 도구는 응답이다.이것은 조금 전에 어려운 이름 변경 및 리팩터링 작업을 위해 작성한 작은 Python 스크립트이다.다음과 같은 이유를 생각할 수 있습니다.

  • 파일 이름 변경 및 파일 내용 검색 및 바꾸기 기능을 지원합니다.
  • 검색 및 치환을 수행하기 전에 변경 사항을 확인하십시오.
  • 백 치환, 전체 단어, 대소문자를 구분하지 않고 대소문자를 구분하지 않는 정규 표현(foo -> bar, foo -> Bar, FOO -> BAR) 모드를 지원합니다.
  • 스와프(foo -> bar and bar -> foo) 또는 고유하지 않은 교환 세트(foo -> bar, f -> x)를 포함한 여러 교환으로 동작합니다.

을 사용하려면 , 「 」를 사용합니다.pip install repren에 대해서는, README참조해 주세요.

이 방법은 효과가 있었습니다.

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

단, 이것은 다음과 같은 것이 아닙니다.sed -i 's/string1/string2/g' * bar일 수 "foo" string1" "bar" string2" "foo" string1" "bar" string2" 입니다.

여러 파일의 문자열을 바꾸려면 다음을 사용합니다.

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

예.

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

소스 블로그

파일내의 패스를 치환(스케이프 문자를 사용하지 않게) 하려면 , 다음의 커맨드를 사용할 수 있습니다.

sed -i 's@old_path@new_path@g'

@ 기호는 다음 문자열에서 모든 특수문자를 무시해야 함을 의미합니다.

「」을 는,search ㅇㅇㅇㄹㄹㄹㄹㄹㄹㄹㄹ and and and 。replace여러 파일에 걸쳐 있는 것은 다음과 같은 한 줄 바꿈의 한 줄 공식:

grep -RiIl 'search' | xargs sed -i 's/search/replace/g'

간단한 GREP 설명:

  • -R - 재귀 검색
  • -i를 구분하지 않음 - 대소문자를 구분하지 않음
  • -I파일 - 바이너리 파일 건너뛰기(텍스트를 원하십니까?)
  • -l - 출력으로 출력합니다.

다음으로 grep 출력은 (xargs 경유로) sed로 파이핑되어 실제로 텍스트를 치환하기 위해 사용됩니다.-i깃발을 들다일종의 "드라이 런" 모드일 경우 제거합니다.

문자열에 슬래시(/)가 포함되어 있는 경우 구분 기호를 '+'로 변경할 수 있습니다.

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

이 명령어는 현재 디렉토리에서 반복적으로 실행됩니다.

사용할 수 있는 파일 목록이 있는 경우

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

모든 파일을 사용할 수 있는 경우

replace "old_string" "new_string" -- *

확장자를 가진 파일 목록이 있는 경우

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

foo의 첫 번째 행은 "bar"로 대체됩니다.그리고 두 번째 줄을 사용하여 확인할 수 있습니다.

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

"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' )

MacBook Pro에서는 다음을 사용했습니다(https://stackoverflow.com/a/19457213/6169225)에서 영감을 받았습니다).

sed -i '' -e 's/<STR_TO_REPLACE>/<REPLACEMENT_STR>/g' *

-i ''이치노

-e모던 정규식용입니다.

나는 이 질문을 찾기 전에 나만의 해결책을 생각해 냈다."replace"와 "several"과 "xml"의 다른 조합을 검색했는데, 이 앱은 찾을 수 없었습니다.

문제:복잡한 오브젝트가 포함된 테스트 케이스용 데이터가 포함된 spring xml 파일을 가지고 있었습니다.Java 소스 코드의 리팩터는 많은 클래스를 변경했으며 xml 데이터 파일에 적용되지 않았습니다.테스트 케이스 데이터를 저장하기 위해 여러 디렉토리에 분산된 모든 xml 파일의 모든 클래스 이름을 변경해야 했습니다.이 모든 것은 원래 xml 파일의 백업 복사본을 저장하면서 이루어집니다(버전 제어로 인해 반드시 필요한 것은 아니었지만).

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★의 조합을 찾고 있었습니다.find+sed왜냐하면 다른 상황에서는 효과가 있었지만, 동시에 여러 번 교체했을 때는 효과가 없었기 때문입니다.

그 후 ask ubuntu 응답을 발견하고 명령줄을 구축하는 데 도움이 되었습니다.

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

그리고 완벽하게 작동했습니다(음, 제 케이스는 6개의 다른 대체품이 있었습니다)., 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' {} \;

정말 재미없지만, SED 명령어를 OSX에서 바로 사용할 수 없어서 대신 이 바보 같은 일을 했습니다.

:%s/foo/bar/g
:wn

^- 이 세 줄을 클립보드에 복사한 다음(예, 끝 줄바꿈 포함):

vi *

파일이 남아 있지 않다고 표시될 때까지 command-v를 누릅니다.

멍청한... 해커... 효과적...

grep --include={*.php,*.html} -rnl './' -e "old" | xargs -i@ sed -i 's/old/new/g' @

multiedit 명령어 스크립트

multiedit [-n PATTERN] OLDSTRING NEWSTRING

Kaspar의 답변에서 명령줄 인수를 받아들이고 선택적으로 패턴에 일치하는 파일 이름을 제한하는 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

한 번에 두 가지 작업을 수행할 수 있도록 메모를 추가하고 싶습니다. 문자열이 포함된 파일을 찾은 다음 '체인' 찾기 방법을 사용하여 바꾸십시오.

find  . -type f -iname \*.php -exec fgrep -l "www." {} \; -exec sed -i "s|www||g" {} \;      
  • 이 경우 PHP 파일에서 발견된 URL에서 시대착오적인 'www'를 제거합니다.

  • 'fgrep -l'은 파일 내에서 하나 이상의 일치 항목을 찾은 경우에만 트리거되며 다른 출력은 생성되지 않습니다.'\;' 구분자를 잊지 마십시오.

는 "inplace"를 때파일을 "합니다.-i: argumentswitch :로 .그게

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

대체하다foobar이 폴더의 모든 파일에 포함되지만 하위 폴더로 내려오지는 않습니다. 이렇게 러러 a a a a a a a a a a가 됩니다..bak디렉토리내의 모든 파일을 파일 합니다.과 그 디렉토리의 모든 , 하려면 , 「」와 같이 헬퍼가 합니다.find이치노

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

find에서는, 「변경할 더 할 수 .」라고 하는 인수는, 「변경할 수 없습니다.」라고 하는 할 수 .find ./ -name '*.php' -or -name '*.html' -print0


GNU 메 gnu : GNUsed엔딩이 필요 .파일 엔딩은 필요 없습니다.sed -i 's/foo/bar/g' * will 、 FreeB 、 FreeB 。SDsed 그 이 있기 에, 「」는 「스페이스」로 할 수 있습니다.sed -i .bak s/foo/bar/g *

퍼스널 영어 노드를 유지하기 위해 디렉토리 내의 모든 파일에 대해 여러 쌍의 오래된 문자열과 새 문자열의 치환을 지원하는 유틸리티 스크립트를 작성했습니다.

오래된 문자열과 새로운 문자열의 여러 쌍이 해시 맵에서 관리됩니다.

dir는 명령줄 또는 환경변수를 사용하여 설정할 수 있으며, 맵은 스크립트로 하드코딩되지만 필요에 따라 파일에서 로드하도록 코드를 변경할 수 있습니다.

새로운 기능으로 인해 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 -i@ sed -i "s/$key/${itemMap[$key]}/g" @
done

echo -e "\nDone."
exit

파일에 백슬래시(통상은 패스)가 포함되어 있는 경우는, 다음과 같이 시험할 수 있습니다.

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

예:

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

ack 명령어를 사용하면 다음과 같이 훨씬 빨라집니다.

ack '25 Essex' -l | xargs sed -i 's/The\ fox \jump/abc 321/g'

검색 결과에 공백이 있는 경우에도 마찬가지입니다.도망쳐야 해

간단한 스크립트 파일을 사용하면 다음과 같은 간단한 방법이 있습니다.

   # sudo chmod +x /bin/replace_string_files_present_dir

파일을 gedit 또는 원하는 에디터로 엽니다.여기서 gedit을 사용합니다.

   # sudo gedit /bin/replace_string_files_present_dir

그런 다음 편집기에서 다음 항목을 파일에 붙여넣습니다.

   #!/bin/bash
   replace "oldstring" "newstring" -- *
   replace "oldstring1" "newstring2" -- *
   #add as many lines of replace as there are your strings to be replaced for 
   #example here i have two sets of strings to replace which are oldstring and 
   #oldstring1 so I use two replace lines.

파일을 저장하고 gedit을 닫은 후 단말기를 종료하거나 단말기를 닫은 후 시작하여 추가한 새 스크립트를 로드합니다.

편집할 파일이 여러 개 있는 디렉토리로 이동합니다.그런 다음 실행합니다.

  #replace_string_files_present_dir

Enter 키를 누르면 포함된 모든 파일의 oldstringoldstring1이 각각 올바른 newstringnewstring1로 자동으로 대체됩니다.

오래된 문자열이 포함되지 않은 모든 디렉토리 및 파일을 건너뜁니다.

이렇게 하면 문자열 치환이 필요한 파일이 여러 개 있는 경우 입력하는 번거로운 작업을 줄일 수 있습니다.각 디렉토리로 이동하여 다음 작업을 수행합니다.

#replace_string_files_present_dir

위에서 설명한 것과 같이 모든 대체 문자열을 포함하거나 추가하기만 하면 됩니다.

replace "oldstring" "newstring" -- *

/bin/replace_string_files_present_files_frecision 파일의 끝에 있습니다.

새 대체 문자열을 추가하려면 터미널에 다음을 입력하여 작성한 스크립트를 여십시오.

sudo gedit /bin/replace_string_files_present_dir

추가한 치환 문자열의 수는 걱정하지 마십시오.오래된 문자열을 찾을 수 없는 경우 이 문자열은 효과가 없습니다.

python 소스의 일반적인 shebang 오류를 수정하기 위한 예를 제시하겠습니다.

grep/sed 어프로치를 시험해 볼 수 있습니다.여기 GNU sed와 연동하여 git repo를 파괴하지 않는 것이 있습니다.

$ 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와 함께 사용하는 것을 숙달하는 것이 좋을지도 모릅니다.

이것은 다른 투고에서 찾았습니다(어느 것이 좋은지 기억나지 않습니다).가장 우아하지는 않지만 심플하고 초보 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

다음 명령을 사용하여 먼저 파일을 검색하고 파일을 바꿀 수 있습니다.

find . | xargs grep 'search string' | sed 's/search string/new string/g'

예를들면

find . | xargs grep abc | sed 's/abc/xyz/g'

많은 답변에 대한 저의 문제는 많은 파일 내의 파일 경로를 교체해야 한다는 것이었습니다.한 회답에 이런 내용이 기재되어 있었지만, 나에게는 통하지 않았다.솔루션:

먼저 변경할 파일 이름 목록을 생성합니다.

filelist=($(find /path/to/your/folder | xargs grep '/path/to/fix' | cut -d : -f 1 | tr '\n' ' '))

에서는 " " "가 동작합니다.find되어 있습니다.grep는, 을 「파일명」으로 합니다./path/to/fix ,,는, ,지,지,grep된 행도 되므로, 「 」는 「 」를 해 주세요.cut명령어는 이 파일을 삭제하고 파일 이름만 유지합니다. tr는 줄바꿈 으로 바꿉니다.에 의해, 「공백」을 사용할 수 .이것에 의해, 다음의 조작이 가능하게 됩니다.filelist배열로 저장됩니다.

for file in "${filelist[@]}"; do sed -i.bak 's+/path/to/fix+/new/path/for/my/file+g' $file; done

★★★★★★★★★★★★★★★★★.sed는 이에 대한 하여 "사용할 수 없습니다"를 사용합니다.+의 「Delimiter」가 , 됩니다./ 이후로는/파일 경로에서 문자를 사용하고 있습니다.

하였습니다.ag: ,_silver_closcher

ag -0 -l 'old' | xargs -0 sed -ri.bak -e 's/old/new/g';

★★★★★★★★★★★★★★★.git clean. 파일(.bak 파일을rm git rebase git rebase를 할 때 가 발생하고 .exec)

git clean -f '**/*.bak';

언급URL : https://stackoverflow.com/questions/11392478/how-to-replace-a-string-in-multiple-files-in-linux-command-line

반응형