Mam plik, który ma kilka nazw hostów skorelowanych z adresami IP, który wygląda następująco:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int.test.example.com 59.2.86.3
super.awesome.machine 123.234.15.6
Chcę, aby wyglądało to tak:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int-test-example-com 59.2.86.3
super-awesome-machine 123.234.15.6
Jak mogę wymienić. (kropki) z pierwszej kolumny z - (łącznikiem), aby ułatwić sortowanie według drugiej kolumny? Myślałem o użyciu seda do zamiany kropek do pierwszej spacji lub o zamianie każdej kropki oprócz trzech ostatnich, ale mam problem ze zrozumieniem wyrażeń regularnych i sed. Mogę wykonywać proste wymiany, ale to jest nad moją głową!
Jest to część większego skryptu, który pisałem bash. Utknąłem w tej części.
awk
jest oparta nanawk
, więc wszystkie nowoczesneawk
implementacje powinny ją miećgsub
. W systemie Solaris możesz potrzebować/usr/xpg4/bin/awk
lubnawk
.Jeśli musisz dokonać podstawienia na pierwszym polu, najlepiej użyć rozwiązania awk Rahula, ale uważaj, może to wpłynąć na odstępy (pola są przepisywane z pojedynczym odstępem między nimi).
Możesz tego uniknąć, pisząc zamiast tego:
Te
-p
środki flag „czytać wiersz po wierszu pliku wejściowego i wydrukować każdą linię po zastosowaniu skryptu podane przez-e
”. Następnie zamień (s|pattern|replacement|
) pierwszą sekwencję znaków spacji (\S+
) na dopasowany wzorzec ($&
) po zastąpieniu wszystkich.
przez-
. Sztuką jest użycies|||e
miejsca, w któryme
operator oceni wyrażenie jako zamiennik. Tak więc możesz zastosować jedną zamiennik (tr/./-/
) do dopasowania ($&
) poprzedniego (s|||e
).Jeśli chcesz zastąpić każdą
.
z-
wyjątkiem ostatnich 3 ostatnich, GNUsed
i zakładając, że maszrev
komendę:źródło
/r
aby działała).Sed nie jest najłatwiejszym narzędziem do pracy - zobacz inne odpowiedzi na lepsze narzędzia - ale można to zrobić.
Aby zastąpić
.
przez-
tylko do pierwszego miejsca, wykorzystanias
w pętli.(Zauważ, że niektóre implementacje sed nie obsługują komentarzy w tej samej linii. GNU sed tak.)
Aby zamiast tego wykonać zamianę do ostatniego miejsca:
Inna technika wykorzystuje przestrzeń ładowni sed. Zapisz fragment, którego nie chcesz modyfikować, w polu blokady, wykonaj swoją pracę, a następnie przywołaj przestrzeń blokady. Tutaj dzielę linię w ostatnim miejscu i zastępuję kropki myślnikami w pierwszej części.
źródło
Ponieważ Rahul udzielił ci kanonicznej odpowiedzi na twój przypadek użycia, pomyślałem, że postaram się odpowiedzieć na tytułowy problem: podstawiając wszystkie oprócz x wystąpień wyrażenia regularnego:
Powyższy kod (przetestowany) nie zakłada, że masz pola rozdzielone spacjami. Zastąpi wszystkie kropki linii kreskami, z wyjątkiem ostatnich 3 kropek. Zastąp
3
kod w swoich upodobaniach.źródło
Możesz użyć do tego wielu różnych narzędzi. Rahul Patil już ci go dał,
gawk
więc oto kilka innych:perl
Te
-a
przyczyny przełączników Perl wejściowych automatycznie podzielone liniami na spacji i zapisać wynikających pola do tablicy@F
. Pierwsze pole, zatem będzie$F[0]
więc zastąpić (s///
) wszystkie wystąpienia.
ze-
w pierwszym polu, a następnie wydrukować całą tablicę.muszla
Tutaj pętla while odczytuje plik i automatycznie dzieli się na białe znaki. Tworzy to dwa pola
$first
i$rest
. Konstrukt${first//pattern/replacement}
zastępuje wszystkie wystąpieniapattern
zreplacement
.źródło
perlrun(1)
powiem ci, że-a
jest to „tryb automatycznego podziału”, wolę myśleć o nim jako o „awk
trybie”: DUważam, że jest to nieco łatwiejsze do odczytania niż duże nieprzyjemne wyrażenie regularne. Zasadniczo po prostu podzieliłem linię na dwa pola w białych znakach i użyłem sed w pierwszej części.
W zależności od powłoki możesz także użyć $ {host //./-} zamiast polecenia sed.
źródło
Bez użycia
g
na końcu polecenia możesz to zrobić… To po prostu zastąpi pierwsze wystąpienie wzorcaźródło