ripgrep(имя командыrg
)— это инструмент grep
, но он также поддерживает поиск и замену.
$ cat ip.txt
dark blue and 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 and 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 and light red
light orange
red sky
rg
не поддерживает вариант размещения -, так что вам придется сделать это самостоятельно
$ # -N isn't needed here as output destination is a file
$ rg --passthru 'blue' -r 'red' ip.txt > tmp.txt && mv tmp.txt ip.txt
$ cat ip.txt
dark red and light red
light orange
red sky
См. Документацию по регулярным выражениям Rust для ознакомления с синтаксисом и функциями регулярных выражений. Переключатель -P
включает вариант PCRE2 . rg
по умолчанию поддерживает Unicode.
$ # non-greedy quantifier is supported
$ echo 'food land bark sand band cue combat' | rg 'foo.*?ba' -r 'X'
Xrk sand band cue combat
$ # unicode support
$ echo 'fox:αλεπού,eagle:αετός' | rg '\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 '[[:punct:]--[.!?]]+' -r ''
Hi there! How are you? All fine here.
$ # use -P if you need even more advanced features
$ echo 'car bat cod map' | rg -P '(bat|map)(*SKIP)(*F)|\w+' -r '[$0]'
[car] bat [cod] map
Как и grep
, опция -F
позволит сопоставлять фиксированные строки, удобная опция, которую, как мне кажется, sed
тоже следует реализовать.
$ printf '2.3/[4]*6\nfoo\n5.3-[4]*9\n' | rg --passthru -F '[4]*' -r '2'
2.3/26
foo
5.3-29
Еще одна удобная опция — -U
, которая включает многострочное сопоставление
$ # (?s) flag will allow. to match newline characters as well
$ printf '42\nHi there\nHave a Nice Day' | rg --passthru -U '(?s)the.*ice' -r ''
42
Hi Day
rg
также может работать с файлами стиля dos -
$ # same as: sed -E 's/\w+(\r?)$/123\1/'
$ printf 'hi there\r\ngood day\r\n' | rg --passthru --crlf '\w+$' -r '123'
hi 123
good 123
Другое преимущество rg
заключается в том, что он, вероятно, будет быстрее, чемsed
$ # 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
$ 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
У меня такая же проблема, тоже Mint 20. Пробовал обновить до ядра 5.8.0 -25, но не помогло.
System: Kernel: 5.8.0-25-generic x86_64 bits: 64 compiler: N/A Desktop: Cinnamon 4.6.7
wm: muffin dm: LightDM Distro: Linux Mint 20 Ulyana base: Ubuntu 20.04 focal
........
Audio: Device-1: Intel Xeon E3-1200 v3/4th Gen Core Processor HD Audio vendor: Lenovo
driver: snd_hda_intel v: kernel bus ID: 00:03.0 chip ID: 8086:0c0c
Device-2: Intel 8 Series/C220 Series High Definition Audio vendor: Lenovo
driver: snd_hda_intel v: kernel bus ID: 00:1b.0 chip ID: 8086:8c20
Device-3: Logitech [G533 Wireless Headset Dongle] type: USB
driver: hid-generic,snd-usb-audio,usbhid bus ID: 3-1:10 chip ID: 046d:0a66
Sound Server: ALSA v: k5.8.0-25-generic
Привет, люди! Я тоже прошел через это в течение нескольких дней и, наконец, решил это.