ripgrep으로 트릭 검색 및 바꾸기
24180 단어 tutoriallinuxsubstitutionripgrep
rg
)은 grep
도구이지만 검색 및 바꾸기도 지원합니다. rg
는 sed
에 대한 유사 대안과는 거리가 멀지만, 여러 줄 교체, 고정 문자열 일치, PCRE2
지원 등과 같은 멋진 기능이 있습니다. 이 게시물은 대체 구문에 대한 개요를 제공하고 일부를 강조 표시합니다. rg
가 sed
를 쉽게 대체하는 경우.전역 검색 및 바꾸기
$ cat ip.txt
dark blue, light blue
light orange
blue sky
# by default, line number is displayed if output destination is stdout
# by default, only lines that matched the given pattern is displayed
# 'blue' is search pattern and -r 'red' is replacement string
$ rg 'blue' -r 'red' ip.txt
1:dark red, light red
3:red sky
# --passthru option is useful to print all lines, whether or not it matched
# -N will disable line number prefix
# this command is similar to: sed 's/blue/red/g' ip.txt
$ rg --passthru -N 'blue' -r 'red' ip.txt
dark red, light red
light orange
red sky
N번째 발생 일치
이전 예에서 볼 수 있듯이
rg
는 모든 항목을 검색하고 바꿉니다. 따라서 입력 줄당 특정 항목만 교체하려면 regexp를 사용하여 창의적이어야 합니다.$ s='see bat hot at but at go gate at sat at but at'
# replace first occurrence only
# same as: sed 's/\bat\b/[xyz]/'
$ echo "$s" | rg --passthru -N '\bat\b(.*)' -r '[xyz]$1'
see bat hot [xyz] but at go gate at sat at but at
# same as: sed 's/\bat\b/[xyz]/3'
# the number within {} is N-1 to replace Nth occurrence, for N>1
$ echo "$s" | rg --passthru -N '^((.*?\bat\b){2}.*?)\bat\b' -r '$1[xyz]'
see bat hot at but at go gate [xyz] sat at but at
# replace last but Nth occurrence, for N>=0
$ echo "$s" | rg --passthru -N '^(.*)\bat\b((.*\bat\b){3})' -r '$1[xyz]$2'
see bat hot at but [xyz] go gate at sat at but at
적절한 해결 방법
rg
는 in-place 옵션을 지원하지 않으므로 직접 수행해야 합니다.# -N isn't needed here as output destination is a file
# same as: sed -i 's/blue/red/g' ip.txt
$ rg --passthru 'blue' -r 'red' ip.txt > tmp.txt && mv tmp.txt ip.txt
$ cat ip.txt
dark red, light red
light orange
red sky
moreutils installed 이 있는 경우
sponge
도 사용할 수 있습니다.rg --passthru 'blue' -r 'red' ip.txt | sponge ip.txt
녹 정규식 및 PCRE2
기본적으로
rg
는 GNU sed
에 비해 훨씬 더 많은 기능을 갖춘 Rust 정규식을 사용합니다. 지원되지 않는 주요 기능은 regexp 정의 내의 역참조입니다(성능상의 이유로). 정규식 구문 및 기능은 Rust regex documentation을 참조하십시오. rg
는 기본적으로 유니코드를 지원합니다.# non-greedy quantifier is supported
$ s='food land bark sand band cue combat'
$ echo "$s" | rg --passthru 'foo.*?ba' -r '[xyz]'
[xyz]rk sand band cue combat
# unicode support
$ echo 'fox:αλεπού,eagle:αετός' | rg --passthru '\p{L}+' -r '($0)'
(fox):(αλεπού),(eagle):(αετός)
# set operator example, remove all punctuation characters except . ! and ?
$ para='"hi", there! how *are* you? all fine here.'
$ echo "$para" | rg --passthru '[[:punct:]--[.!?]]+' -r ''
hi there! how are you? all fine here.
-P
스위치는 더 많은 트릭이 있는 PCRE2 플레이버를 활성화합니다. --engine=auto
를 사용하여 필요할 때 rg
가 자동으로 PCRE2
를 사용하도록 할 수도 있습니다(예: rg
명령의 별칭으로 유용하여 기본적으로 Rust 엔진의 성능을 제공하고 필요).# backreference within regexp definition
$ s='cocoa appleseed tool speechless'
$ echo "$s" | rg --passthru -wP '([a-z]*([a-z])\2[a-z]*){2}' -r '{$0}'
cocoa {appleseed} tool {speechless}
# replace all whole words except 'imp' and 'ant'
$ s='tiger imp goat eagle ant important'
$ echo "$s" | rg --passthru -P '\b(imp|ant)\b(*SKIP)(*F)|\w+' -r '[$0]'
[tiger] imp [goat] [eagle] ant [important]
# recursively match parentheses
$ eqn='(3+a)x * y((r-2)*(t+2)/6) + z(a(b(c(d(e)))))'
$ echo "$eqn" | rg --passthru -P '\((?:[^()]++|(?0))++\)' -r ''
x * y + z
$ # all lowercase letters and optional hyphen combo from start of string
$ s='apple-fig-mango guava grape'
$ echo "$s" | rg --passthru -P '\G([a-z]+)(-)?' -r '($1)$2'
(apple)-(fig)-(mango) guava grape
추출 및 수정
PCRE2
옵션은 -r
옵션이 활성화된 경우에도 사용할 수 있습니다. 아래의 예는 -o
로 하기가 쉽지 않습니다.$ s='0501 035 154 12 26 98234'
# numbers >= 100 and ignore leading zeros
$ echo "$s" | rg -woP '0*+(\d{3,})' -r '"$1"' | paste -sd,
"501","154","98234"
고정 문자열 일치
sed
와 같이 grep
옵션을 사용하면 고정 문자열을 일치시킬 수 있습니다. 모든 검색 및 바꾸기 도구가 제공해야 하는 편리한 옵션입니다.$ printf '2.3/[4]*6\nfoo\n5.3-[4]*9\n' | rg --passthru -F '[4]*' -r '2'
2.3/26
foo
5.3-29
-F
는 대체 섹션으로 확장되지 않으므로 문자 그대로 표현하려면 -F
문자 대신 $$
가 필요합니다.$ echo 'a.*{2}-b' | rg --passthru -F '.*{2}' -r '+$x\tc'
a+\tc-b
$ echo 'a.*{2}-b' | rg --passthru -F '.*{2}' -r '+$$x\tc'
a+$x\tc-b
여러 줄 일치
또 다른 편리한 옵션은 여러 줄 일치를 활성화하는
$
입니다.$ s='hi there\nhave a nice day\nbye'
# (?s) flag will allow . to match newline characters as well
$ printf '%b' "$s" | rg --passthru -U '(?s)the.*ice' -r ''
hi day
bye
도스 스타일 입력 처리
-U
는 rg
옵션을 사용하여 도스 스타일 파일에 대한 지원을 제공합니다.# same as: sed -E 's/\w+(\r?)$/xyz\1/'
# note that output will retain CR+LF as line ending
# similar to the sed solution, this will work for unix-style input too
$ printf 'hi there\r\ngood day\r\n' | rg --passthru --crlf '\w+$' -r 'xyz'
hi xyz
good xyz
GNU sed와 속도 비교
--crlf
의 또 다른 장점은 rg
보다 빠를 가능성이 높다는 것입니다. 방법론적 세부 분석 및 통찰력은 저자의 ripgrep benchmark with other grep implementations 참조.# for small files, initial processing time of rg is a large component
$ time echo 'aba' | sed 's/a/b/g' > f1
real 0m0.002s
$ time echo 'aba' | rg --passthru 'a' -r 'b' > f2
real 0m0.007s
# for larger files, rg is likely to be faster
# 6.2M sample ASCII file
$ wget 'https://norvig.com/big.txt'
$ time LC_ALL=C sed 's/\bcat\b/dog/g' big.txt > f1
real 0m0.060s
$ time rg --passthru '\bcat\b' -r 'dog' big.txt > f2
real 0m0.048s
$ diff -s f1 f2
Files f1 and f2 are identical
# nearly 8 times faster!!
$ time LC_ALL=C sed -E 's/\b(\w+)(\s+\1)+\b/\1/g' big.txt > f1
real 0m0.725s
$ time rg --no-unicode --passthru -wP '(\w+)(\s+\1)+' -r '$1' big.txt > f2
real 0m0.093s
$ diff -s f1 f2
Files f1 and f2 are identical
sed의 다른 대안
rpl — 검색 및 바꾸기 도구, 대화형 모드 및 재귀 모드와 같은 흥미로운 옵션이 있습니다
sd — 간단한 검색 및 바꾸기, Rust에서 구현됨
perl 및 ruby — 탁월한 명령줄 지원 기능이 있는 프로그래밍 언어
Reference
이 문제에 관하여(ripgrep으로 트릭 검색 및 바꾸기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/learnbyexample/search-and-replace-tricks-with-ripgrep-59lk텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)