정규 표현식이없는 ** 텍스트 파일의 대체 **


68

텍스트 파일 내부의 일부 텍스트를 대체물로 바꿔야합니다. 보통 나는 다음과 같은 일을 할 것입니다

sed -i 's/text/replacement/g' path/to/the/file

문제는 둘 것입니다 textreplacement등등 대시, 슬래시, blackslashes 따옴표 등을 포함 complex 문자열이다. 내가 필요한 모든 문자를 피 text하면 물건을 빨리 읽을 수 없게됩니다. 반면에 나는 정규 표현식의 힘이 필요하지 않습니다. 텍스트를 문자 그대로 대체하면됩니다.

bash 명령에 정규식을 사용 하지 않고 텍스트를 대체하는 방법이 있습니까?

이 작업을 수행하는 스크립트를 작성하는 것은 사소한 일이지만 이미 무언가 존재해야한다고 생각합니다.


배쉬를 통해 그것을해야합니까? 간단한 해결책은 Word에서 열고find and replace all
Akash

17
@akash bash항상 Microsoft Word와 함께 제공 되는 시스템 입니까? ;) 장난 치지 마. OP는 원격 컴퓨터 또는 파일 배치 에서이 작업을 수행하려고 할 수 있습니다.
slhck

@slhck :) 글쎄, 나는 gedit도 비슷한 옵션을 가져야한다고 생각한다
Akash

옵션이하는 것입니다 어떻게 든 제대로 전달하기 전에 모든 탈출 sed아마 모든 스위치 및 플랫폼의 차이를 고려하여 쓸데없는 노력이다.
l0b0

답변:


6

정규 표현식의 힘이 필요하지 않으면 사용하지 마십시오. 괜찮습니다.
그러나 이것은 실제로 정규 표현식 이 아닙니다 .

sed 's|literal_pattern|replacement_string|g'

따라서 /문제가 있다면 사용 |하고 전자를 피할 필요가 없습니다.

추신 : 의견에 대해서는 sed search pattern의 문자열 이스케이프 에 대한이 Stackoverflow 답변을 참조하십시오 .


업데이트 : 당신이 잘 사용하는 경우 펄을 함께 시도 \Q\E같이,
perl -pe 's|\Qliteral_pattern\E|replacement_string|g'
RedGrittyBrick여기 댓글에 강한 펄 구문과 비슷한 트릭을 제안했다


감사합니다. /와 |의 차이점에 대해 몰랐습니다.
Andrea

64
나는이 대답은 유용 모르겠어요 ... 유일한 차이점 s|||s///구분자 문자가 너무 다르고 있다는 하나 개의 문자가 이스케이프 필요가 없습니다. 당신도 똑같이 할 수 s###있습니다. 여기서 실제 문제는 OP가 내용을 탈출하는 것에 대해 걱정할 필요 literal_pattern가 없다는 것 입니다 (이는 문자 그대로가 아니며 정규식으로 해석됩니다).
Benj

15
이것은 다른 특수 문자의 해석을 피하지 않습니다. 무엇을 검색하는 경우 1234.*aaa솔루션으로는 의도 한 것보다 훨씬 더 일치 1234\.\*aaa.
Matteo

20
이 답변을 수락 해서는 안됩니다
Steven Lu

2
이것은 요점을 완전히 놓친다. 일치시킬 텍스트는 모든 증오를 포함 할 수 있습니다. 제 경우에는 임의의 암호입니다. 당신은 어떻게되는지 알고
Christian Bongiorno

13
export FIND='find this'
export REPLACE='replace with this'
ruby -p -i -e "gsub(ENV['FIND'], ENV['REPLACE'])" path/to/file

이것은 다음과 같은 이유로 100 % 안전한 솔루션입니다.

  • 그것은 (사용하는 우수한 따라서, 정적 substition 아닌 정규 표현식, 아무것도 탈출 할 필요있어 sed)
  • 문자열에 }char이 포함되어 있으면 중단되지 않습니다 (따라서 제출 된 Perl 솔루션보다 우수합니다)
  • ENV['FIND']는 사용되지 않기 때문에 어떤 문자로도 중단 되지 않습니다 $FIND. 함께 $FIND또는 텍스트를 루비 코드에서 인라인 귀하의 문자열을 이스케이프 포함 된 경우, 당신은 구문 오류를 칠 수있다 '.

내가 사용했다 export FIND='find this; export REPLACE='replace with this';그래서 내 bash는 스크립트 ENV['FIND']ENV['replace']예상 값을했다. 파일에서 정말로 긴 암호화 된 문자열을 바꾸고있었습니다. 이것은 단지 티켓이었다.
DMfll

이것은 신뢰할 수 있고 루비는 어디에나 있기 때문에 정답입니다. 이 답변을 바탕 으로이 쉘 스크립트를 사용 합니다 .
loevborg

불행히도 FIND에 여러 줄이 포함되어 있으면 작동하지 않습니다.
adrelanos

FIND에서 여러 줄로 작업하지 못하게하는 것은 없습니다. 큰 따옴표 \ n을 사용하십시오.
Nowaker

7

replace명령은이 작업을 수행 할 것입니다.

https://linux.die.net/man/1/replace

장소 변경 :

replace text replacement -- path/to/the/file

표준 출력 :

replace text replacement < path/to/the/file

예:

$ replace '.*' '[^a-z ]{1,3}' <<EOF
> r1: /.*/g
> r2: /.*/gi
> EOF
r1: /[^a-z ]{1,3}/g
r2: /[^a-z ]{1,3}/gi

replace명령은 MySQL 또는 MariaDB와 함께 제공됩니다.


3
교체는 더 이상 사용되지 않으며 향후에는 불가능할 수 있습니다.
Rogelio

1
왜 지구상에서 이러한 기본 명령이 데이터베이스와 함께 제공됩니까?
masterxilo

3
@masterxilo 더 좋은 질문은 왜 그러한 기본 명령이 최신 운영 체제와 함께 제공되지 않습니까? ;-)
Mark Thomson


3

내 Perl 스크립트를 확인하십시오. 정규 표현식의 암시 적 또는 명시 적 사용없이 필요한 것을 정확하게 수행합니다.

https://github.com/Samer-Al-iraqi/Linux-str_replace

str_replace Search Replace File # replace in File in place

STDIN | str_replace Search Replace # to STDOUT

매우 편리합니까? 나는 그것을하기 위해 Perl을 배워야했다. 정말 정말로 필요하기 때문입니다.


2

패턴 을 이스케이프 처리하면됩니다 . 이처럼 :

keyword_raw='1/2/3'
keyword_regexp="$(printf '%s' "$keyword_raw" | sed -e 's/[]\/$*.^|[]/\\&/g')"
# keyword_regexp is now '1\/2\/3'

replacement_raw='2/3/4'
replacement_regexp="$(printf '%s' "$replacement_raw" | sed -e 's/[\/&]/\\&/g')"
# replacement_regexp is now '2\/3\/4'

echo 'a/b/c/1/2/3/d/e/f' | sed -e "s/$keyword_regexp/$replacement_regexp/"
# the last command will print 'a/b/c/2/3/4/d/e/f'

이 솔루션에 대한 크레딧은 여기에 있습니다 : https : //.com/questions/407523/escape-a-string-for-a-sed-replace-pattern

참고 1 : 이것은 비어 있지 않은 키워드에만 적용됩니다. 빈 키워드는 sed ( sed -e 's//replacement/')에서 허용되지 않습니다 .

참고 2 : 불행히도, 나는 regexp-s를 사용하여 문제를 해결하지 않는 인기있는 도구를 모른다. 이러한 도구를 Rust 또는 C로 작성할 수 있지만 기본적으로는 없습니다.


이것은 OP의 요점을 완전히 놓친 것입니다. 분명히 패턴을 벗어날 수는 있지만 일부 패턴의 경우 지루합니다.
icecreamsword

@icecreamsword 첫 줄 아래에서 내 대답을 읽었습니까? 스크립트는 자동으로 빠져 나갑니다 .
VasyaNovikov

1

나는 몇 가지 다른 답변을 모아서 이것을 생각해 냈습니다.

function unregex {
   # This is a function because dealing with quotes is a pain.
   # http://stackoverflow.com/a/2705678/120999
   sed -e 's/[]\/()$*.^|[]/\\&/g' <<< "$1"
}
function fsed {
   local find=$(unregex "$1")
   local replace=$(unregex "$2")
   shift 2
   # sed -i is only supported in GNU sed.
   #sed -i "s/$find/$replace/g" "$@"
   perl -p -i -e "s/$find/$replace/g" "$@"
}

개행과 함께 작동하지 않습니다. 또한 개행을 피하는 데 도움이되지 않습니다 \n. 어떤 해결책?
adrelanos

1

PHP의 str_replace를 사용할 수 있습니다 :

php -R 'echo str_replace("\|!£$%&/()=?^\"'\''","replace",$argn),PHP_EOL;'<input.txt >output.txt

참고 : 그래도 작은 따옴표 '와 큰 따옴표 를 이스케이프해야합니다 ".


0

@Nowaker와 동일한 Node.JS :

export FNAME='moo.txt'
export FIND='search'
export REPLACE='rpl'
node -e 'fs=require("fs");fs.readFile(process.env.FNAME,"utf8",(err,data)=>{if(err!=null)throw err;fs.writeFile(process.env.FNAME,data.replace(process.env.FIND,process.env.REPLACE),"utf8",e=>{if(e!=null)throw e;});});'

0

여기에 "거의"작동 방식이 하나 더 있습니다.

vi 또는 vim을 사용하십시오.

대체 텍스트 파일을 작성하십시오.

: % sno / my 검색 문자열 \\ "-: # 2; g ( '. j'); \\"> / my replacestring = \\ "bac) (o : # 46; \\"> /
:엑스

그런 다음 명령 행에서 vi 또는 vim을 실행하십시오.

vi -S commandfile.txt path/to/the/file

: % sno는 마법없이 검색하고 바꾸는 vi 명령입니다.

/는 내가 선택한 구분자입니다.

: x는 vi를 저장하고 종료합니다.

백 슬래시 '\'를 이스케이프해야합니다. 슬래시 '/'는 예를 들어 물음표 '?'로 대체 될 수 있습니다. 또는 검색 또는 바꾸기 문자열에없는 다른 것, 파이프 '|' 나를 위해 작동하지 않았다.

참조 : https://stackoverflow.com/questions/6254820/perform-a-non-regex-search-replace-in-vim https://vim.fandom.com/wiki/Search_without_need_to_escape_slash http://linuxcommand.org/ lc3_man_pages / vim1.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.