Kolumna bez ostatnich znaków z awk i printf

0

Pytanie

Mam ten skrypt:

#!/bin/bash

f_status () {
        systemctl list-units | grep $1 | awk '{ printf("SERVICE STATUS:  %-25s \t %s \t %s \t %s\n",$1,$2,$3,$4) }'
}

f_line() {
        echo "-------------------------------------------------------------------------------------------"
}

echo ""
f_line
f_status "cron"
f_status "ssh"
f_line

Ten skrypt daje mi taki wynik:

-------------------------------------------------------------------------------------------
SERVICE STATUS:  cron.service                    loaded          active          running
SERVICE STATUS:  ssh.service                     loaded          active          running
-------------------------------------------------------------------------------------------

i szukam, jak usunąć ".service" z kolumny 3d.

Próbowałem z substr($i, 0, -8) i ${1:-8}

Czy ktoś ma pomysł jak pozbyć się z 8 znaków od końca, żeby to wyglądało tak:

-----------------------------------------------------------------------------------
SERVICE STATUS:  cron                    loaded          active          running
SERVICE STATUS:  ssh                     loaded          active          running
-----------------------------------------------------------------------------------
awk bash printf
2021-11-23 11:39:15
3

Najlepsza odpowiedź

0

Nigdy nie będziesz potrzebować grep, gdy używasz awk, tak jak grep 'foo' file | awk '{print 7}' może być napisana tylko awk '/foo/{print 7}' file.

Zamiast liczyć znaki, po prostu usuń wszystko, począwszy od ostatniego .:

systemctl list-units |
awk -v tgt="$1" '
    {
        svc = $1
        sub(/\.[^.]*$/,"",svc)
    }
    svc == tgt {
        printf "SERVICE STATUS:  %-25s \t %s \t %s \t %s\n",svc,$2,$3,$4
    }
'

Ja również zaostrzyły swoje porównanie, aby uniknąć fałszywych alarmów podczas rozmowy z nazwą usługi, która jest podzbiorem jakiejś innej nazwy usługi lub zawiera metaznaki wyrażeń regularnych, takich jak ..

2021-11-23 12:10:21

Dziękuję za mega szybką odpowiedź. Dziękuję również za wskazówki "grep" i "awk" - będę miał to na uwadze. Spędziłem 4 godziny na to zadanie i nie miał pojęcia, jak go rozwiązać.
gacek

Wybrałem rozwiązanie i przestrzegać zaleceń dotyczących zachowania po odpowiedzi. Jeszcze raz dziękuję i pozdrawiam!
gacek
0

Trzeba obliczyć końcową na podstawie długości wiersza, rozważmy następujący prosty przykład, niech file.txt zawartość będzie

cron.service
ssh.service

następnie

awk '{print substr($1,1,length($1)-8)}' file.txt

wyjście

cron
ssh

Wyjaśnienie: argumenty na rzeczsubstr są wierszem, w początkowej pozycji, ostatecznym stanowiskiem, length zwraca liczbę znaków w wierszu.

(sprawdzone w gawk 4.2.1)

2021-11-23 12:04:06

Dzięki za wyjaśnienie. Próbowałem ten sposób wcześniej: substr($1, długość, -8), ale nie sądziłem, że mi się należy podać zmienną, która powinna liczyć ilość znaków.
gacek

@гачек length podczas korzystania bez () to po prostu zmienna zawierająca liczbę znaków w całym wierszu ($0), a nie konkretne pole, na przykład, jeśli masz plik z jednym wierszem: 123 456 następnie {print length} daje 7tak jak on składa się z 6 cyfr i spacji.
Daweo

stosunkowo length when used without () is just variable - nie, to wciąż wywołanie funkcji, to po prostu skrót length($0). Gdyby to była zmienna, to, między innymi, można przypisać jej wartość, ale nie można.
Ed Morton
0

Można użyć gsub funkcja w awk,na przykład, następujące:

 systemctl list-units | grep 'cron' | awk '{gsub(".service","",$1); printf("SERVICE STATUS:  %-25s \t %s \t %s \t %s\n",$1, $2 ,$3,$4) }'
SERVICE STATUS:  crond                       loaded      active      running
2021-11-23 12:04:26

1) gsub() przeznaczony jest do wykonywania wielu zamienników, podczas gdy chcesz zrobić tylko 1, więc trzeba korzystać sub() zamiast tego 2) pierwszy argument dla każdego z *sub() funkcje-jest to wyrażenie regularne, a nie wiersz, dlatego należy użyć wyrażenie regularne /.../nie wiersz "...", separatory, 3) należy zabezpieczyć swoją wyrażenie regularne końcowym $ w ten sposób usuniesz ostatnie wystąpienie w wierszu, a nie pierwszą rzeczą, 4) trzeba uniknąć . w wyrażeniu regularnym, czy on będzie pasował do każdego znaku, a nie tylko . chcesz dopasować, 5) nie musisz grep kiedy używasz awk z grep 'cron' | awk '{foo}' = awk '/cron/{foo}'.
Ed Morton

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................