Próbuję użyć SED do wyodrębnienia tekstu z pliku dziennika. Mogę przeprowadzić wyszukiwanie i zamianę bez większych problemów:
sed 's/foo/bar/' mylog.txt
Jednak chcę, aby w wyszukiwaniu nie była rozróżniana wielkość liter. Z tego, co wyszukałem w Google, wygląda na to, że dołączanie i
do końca polecenia powinno działać:
sed 's/foo/bar/i' mylog.txt
Jednak powoduje to wyświetlenie komunikatu o błędzie:
sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'
Co tu jest nie tak i jak to naprawić?
macos
replace
sed
case-insensitive
Craig Walker
źródło
źródło
I
jest rozszerzeniem GNU, które może nie być dostępne z twoją kopią seda.man sed
JEST zgodny z implementacją - nie ma wzmianki o dopasowywaniu bez uwzględniania wielkości liter (i brak wsparcia w praktyce); Jeśli znalazłeś dokument, w którym twierdzi się inaczej, daj nam znać.g
prefiksem, więc mogę użyćgsed
lubgdate
gdy potrzebuję funkcji, której nie ma w wersji podstawowej.Odpowiedzi:
Aktualizacja : Począwszy MacOS Big Sur (11,0) ,
sed
teraz nie obsługujeI
flagę na wielkość liter , więc komenda w pytaniu powinny teraz działać (BSDsed
nie zgłasza swój wersji, ale można przejść przez dzień na dole odman
strony, która powinna byćMarch 27, 2017
lub nowszym); prosty przykład:# BSD sed on macOS Big Sur and above (and GNU sed, the default on Linux) $ sed 's/ö/@/I' <<<'FÖO' F@O # `I` matched the uppercase Ö correctly against its lowercase counterpart
Uwaga:
I
(wielkie litery) to udokumentowana forma flagi, alei
działa również.Podobnie, począwszy od systemu macOS Big Sur (11.0) jest
awk
teraz uwzględniany język (awk --version
powinien zgłosić20200816
lub nowszy):# BSD awk on macOS Big Sur and above (and GNU awk, the default on Linux) $ awk 'tolower($0)' <<<'FÖO' föo # non-ASCII character Ö was properly lowercased
Poniższe informacje dotyczą macOS do Catalina (10.15) :
Dla jasności: w systemie macOS
sed
- który jest implementacją BSD - NIE obsługuje dopasowywania bez uwzględniania wielkości liter - trudno w to uwierzyć, ale prawda. Wcześniej zaakceptowane odpowiedź , która sama pokazuje GNUsed
polecenia, zyskał ten status z powoduperl
opartym roztworu wzmiankowanym w komentarzach.Aby to rozwiązanie Perla działało również z obcymi znakami , za pośrednictwem UTF-8, użyj czegoś takiego:
-C
włącza obsługę UTF-8 dla strumieni i plików, zakładając, że bieżące ustawienia regionalne są oparte na UTF-8.-Mutf8
mówi Perlowi, aby zinterpretował kod źródłowy jako UTF-8 (w tym przypadku ciąg przekazany do-pe
) - jest to krótszy odpowiednik bardziej szczegółowego-e 'use utf8;'.
Dziękuję, Mark Reed(Zauważ, że używanie również
awk
nie jest opcją , ponieważawk
w macOS (tj. BWK awk i BSD awk ) wydaje się być całkowicie nieświadome ustawień narodowych - jegotolower()
itoupper()
funkcje ignorują obce znaki (isub()
/gsub()
nie mają na początku flag niewrażliwych na wielkość liter z).)Uwaga na temat relacji
sed
iawk
do standardu POSIX:BSD
sed
iawk
ograniczają ich funkcjonalność głównie do tego, co nakazują specyfikacje POSIXsed
i POSIXawk
, podczas gdy ich odpowiedniki w GNU implementują znacznie więcej rozszerzeń.źródło
Uwaga redaktora : to rozwiązanie nie działa na macOS (po wyjęciu z pudełka), ponieważ dotyczy tylko GNU
sed
, podczas gdy macOS jest dostarczany z BSDsed
.Wykorzystaj „ja”.
źródło
I
Przyrostek nie jest przenośnym wykorzystaniesed
. POSIXsed
używa tylko podstawowych wyrażeń regularnych (BRE), które są zaskakująco ograniczone. Nie obsługują nawet+
(musisz użyć\{1,\}
zamiast tego), nie mówiąc już o dopasowywaniu bez uwzględniania wielkości liter. Jedynym przenośnym sposobem na zrobienie tego z sedem jest sprawdzenie czegoś takiego/[hH][eE][lL][lL][oO]/
, co często jest niepraktyczne./gI
przeciwnym razie zadziała tylko na pierwszym meczu.Innym obejściem
sed
w systemie Mac OS X jest instalacjagsed
z MacPorts lub HomeBrew, a następnie utworzenie aliasused='gsed'
.źródło
brew install gnu-sed
następnie przeszedł do mojego ~ / .bash_profile i dodał alias. Dzięki @davmatbrew install gnu-sed --with-default-names
- spowoduje to zastąpienie wartości domyślnejsed
.W sed FAQ rozwiązuje ściśle powiązany wielkości liter wyszukiwania . Wskazuje, że a) wiele wersji seda obsługuje flagę i b) jest to niewygodne w sedzie, powinieneś raczej używać awk lub Perl.
Ale aby to zrobić w sedzie POSIX , sugerują trzy opcje (dostosowane tutaj do podstawienia):
Konwertuj na wielkie litery i przechowuj oryginalny wiersz w pustej przestrzeni; nie zadziała to jednak w przypadku podstawień, ponieważ oryginalna zawartość zostanie przywrócona przed wydrukowaniem, więc nadaje się tylko do wstawiania lub dodawania wierszy na podstawie dopasowania bez uwzględniania wielkości liter.
Może możliwości są ograniczone
FOO
,Foo
afoo
. Można je pokryćAby wyszukać wszystkie możliwe dopasowania, można użyć wyrażeń nawiasowych dla każdego znaku:
źródło
Jeśli najpierw dopasowujesz wzorce, np.
następnie chcesz wstawić
I
po wzorze:Przykład:
zwroty
willma
; bezI
znaku zwraca ciąg nietknięty (Fred
).źródło
sed: 1: "/fred/Is//willma/g": invalid command code I
sed -r '/'"$PATTERN"'/I,${s//'$YELLOW'&'$NO_COLOR'/g;b};$q3'
. Drukuje tekst, a jeśli znaleziono wzór (bez rozróżniania wielkości liter), podświetla tekst na żółto (kolor ansi). Jeśli nie zostanie znaleziony - zwraca kod zakończenia 3.Wersja Mac
sed
wydaje się nieco ograniczona. Jednym ze sposobów obejścia tego jest użycie kontenera linux (przez Docker), który ma użyteczną wersjęsed
:źródło
Miałem podobną potrzebę i wymyśliłem to:
to polecenie, aby po prostu znaleźć wszystkie pliki:
ten, aby wykluczyć this_shell.sh (na wypadek, gdybyś umieścił polecenie w skrypcie o nazwie this_shell.sh ), wyświetl dane wyjściowe konsoli, aby zobaczyć, co się stało, a następnie użyj seda na każdej znalezionej nazwie pliku, aby zastąpić tekst foo barem :
Wybrałem tę metodę, ponieważ nie podobało mi się, gdy wszystkie znaczniki czasu były zmieniane dla plików, które nie zostały zmodyfikowane. podanie wyniku grep umożliwia przeglądanie tylko plików z tekstem docelowym (w ten sposób prawdopodobnie może również poprawić wydajność / szybkość)
pamiętaj, aby wykonać kopię zapasową plików i przetestować przed użyciem. Może nie działać w niektórych środowiskach w przypadku plików z osadzonymi spacjami. (?)
źródło
Użyj następującego, aby zamienić wszystkie wystąpienia: sed 's / foo / bar / gI' mylog.txt
źródło
I
. Nie sądzę też, że to naprawdę odpowiada na pytanie, ponieważ nie dotyczy globalnej wymiany.