Czy mogę zastąpić wiele elementów w jednym wyrażeniu regularnym w Vimie lub perlu?
Powiedzmy, że mam ciąg "szybki brązowy lis przeskakuje nad leniwym psem "czy Mogę zmienić to na" powolny brązowy lis przeskakuje nad energicznym psem " z jednym wyrażeniem regularnym? Obecnie używam w tej sytuacji dwóch zestawów wyrażeń regularnych. (W tym przypadku używam s/quick/slow/
, a następnie s/lazy/energetic/
.)
7 answers
Druga część podstawienia jest podwójnym cytowanym ciągiem, więc może wystąpić każda normalna interpolacja. Oznacza to, że możesz użyć wartości przechwytywania do indeksowania w hash:
#!/usr/bin/perl
use strict;
use warnings;
my %replace = (
quick => "slow",
lazy => "energetic",
);
my $regex = join "|", keys %replace;
$regex = qr/$regex/;
my $s = "The quick brown fox jumps over the lazy dog";
$s =~ s/($regex)/$replace{$1}/g;
print "$s\n";
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-19 19:08:15
Możesz to zrobić w Vimie używając słownika:
:%s/quick\|lazy/\={'quick':'slow','lazy':'energetic'}[submatch(0)]/g
Spowoduje to zmianę następującego tekstu:
The quick brown fox Run quick ly next to the lazy brook.
Do:
Powoli brown fox biegłpowoli ly obok energiczny potok.
Aby zobaczyć jak to działa, zobacz :help sub-replace-expression
i :help Dictionary
. W skrócie,
-
\=
pozwala zastąpić w wynik wyrażenia vim. -
{'quick':'slow', 'lazy':'energetic'}
jest słownikiem vim (jak hash w Perlu lub ruby lub obiekt w javascript), który używa[]
do wyszukiwania. -
submatch(0)
jest dopasowanym ciągiem
Może się to przydać podczas refaktoryzacji kodu-powiedzmy, że chcesz wymienić nazwy zmiennych na foo
, bar
, and baz
changing
-
foo
→bar
-
bar
→baz
-
baz
→foo
Używając sekwencji %s///
polecenia byłyby trudne, chyba że użyjesz tymczasowych nazw zmiennych - ale musisz się upewnić, że nie uderzają w nic innego. Zamiast tego możesz użyć słownika, aby zrobić to w jednym przejściu: {]}
:%s/\<\%(foo\|bar\|baz\)\>/\={'foo':'bar','bar':'baz','baz':'foo'}[submatch(0)]/g
Który zmienia ten kod
int foo = 0;
float bar = pow(2.0, (float) foo);
char baz[256] = {};
sprintf(baz,"2^%d = %f\n", foo, bar);
Do:
int bar = 0;
float baz = pow(2.0, (float) bar);
char foo[256] = {};
sprintf(foo,"2^%d = %f\n", bar, baz);
Jeśli często to robisz, możesz dodać do swojego ~/.vimrc
:
" Refactor the given lines using a dictionary
" replacing all occurences of each key in the dictionary with its value
function! Refactor(dict) range
execute a:firstline . ',' . a:lastline . 's/\C\<\%(' . join(keys(a:dict),'\|'). '\)\>/\='.string(a:dict).'[submatch(0)]/ge'
endfunction
command! -range=% -nargs=1 Refactor :<line1>,<line2>call Refactor(<args>)
Pozwala to na użycie polecenia :Refactor {'frog':'duck', 'duck':'frog'}
i jest nieco
mniej powtarzalne niż tworzenie regex dla dict ręcznie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-27 09:22:06
Możesz konkatenować podstawienia Vima:
Szybki Lis brunatny biegł szybko obok leniwego potoku.
:s/quick/slow/|s/lazy/energetic/
Powolny Lis brunatny biegł szybko obok energicznego potoku.
Zaletą jest to, że musisz wpisać swoje podstawienia tylko raz
Rgds
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-03 15:43:58
Możesz wykonać następujące czynności.
:%s/quick\(.*\)lazy/slow\1energetic
Sztuką jest użycie parentów, aby dopasować tekst między tymi dwoma słowami. Następnie możesz odwołać się do tego tekstu w ciągu zastępczym za pomocą \1
. Możesz również użyć \2
dla drugiego dopasowanego wyrażenia paren i tak dalej. Pozwala to na zastąpienie wielu słów bez zakłócania tekstu inbetween.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-19 19:06:45
W Perlu:
s/quick(.*)lazy/slow${1}energetic/;
W vim:
s/quick\(.*\)lazy/slow\1energetic/;
ODPOWIEDŹ Chasa jest dobra, jedyną inną rzeczą, o której bym wspomniał, jest to, że jeśli robisz zamianę słów, prawdopodobnie chcesz być dopasowany na
\B (foo|bar|baz|qux)\B
Aby uniknąć pasujących podciągów. Jeśli wykonujesz lot zamiany słów, możesz zacząć odnajdywać wyrażenia regularne nieco ograniczające i chcieć zrobić coś w stylu:
join '', map { exists $subst{$_} ? $subst{$_} : $_ } split /\b/, $string
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-19 22:57:22
Jest świetny sposób, aby to zrobić w Ruby używając gsub z blokiem:
s = "The quick brown fox jumps over the lazy dog"
subs = {'quick' => 'slow', 'lazy' => 'industrious'}
s.gsub(/quick|lazy/) { |match| subs[match] }
# => "The slow brown fox jumps over the industrious dog"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-19 19:36:33