Столбец без последних символов с awk и printf

0

Вопрос

У меня есть этот сценарий:

#!/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

Этот скрипт дает мне такой результат:

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

и я ищу, как удалить ".service" из столбца 3d.

Я попробовал с substr($i, 0, -8) и ${1:-8}

У кого-нибудь есть идеи, как избавиться от 8 символов с конца, чтобы это выглядело так:

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

Лучший ответ

0

Вам никогда не понадобится grep, когда вы используете awk, так как grep 'foo' file | awk '{print 7}' может быть записано как просто awk '/foo/{print 7}' file.

Вместо того, чтобы считать символы, просто удалите все, начиная с последнего .:

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
    }
'

Я также ужесточил ваше сравнение, чтобы избежать ложных совпадений при вызове с именем службы, которое является подмножеством какого-либо другого имени службы или содержит метасимволы регулярных выражений, такие как ..

2021-11-23 12:10:21

Спасибо Вам за мега быстрый ответ. Спасибо также за советы по "grep" и "awk" - я буду иметь это в виду. Я потратил 4 часа на эту задачу и понятия не имел, как ее решить.
gacek

Я выбрал Ваше решение и следовал вашим рекомендациям по поведению после ответа. Еще раз спасибо и с наилучшими пожеланиями!
gacek
0

Вам нужно вычислить конечную позицию на основе длины строки, рассмотрим следующий простой пример, пусть file.txt содержание будет

cron.service
ssh.service

затем

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

выход

cron
ssh

Объяснение: аргументы в пользуsubstr являются строкой, начальной позицией, конечной позицией, length возвращает количество символов в строке.

(проверено в gawk 4.2.1)

2021-11-23 12:04:06

Спасибо за объяснение. Я пробовал этот способ раньше: substr($1, длина, -8), но я не думал, что мне следует указывать переменную, которая должна подсчитывать количество символов.
gacek

@гачек length при использовании без () это просто переменная, содержащая количество символов во всей строке ($0), а не конкретное поле, например, если у вас будет файл с одной строкой: 123 456 затем {print length} дает 7, так как он состоит из 6 цифр и пробела.
Daweo

относительно length when used without () is just variable - нет, это все еще вызов функции, это просто сокращение для length($0). Если бы это была переменная, то, помимо прочего, вы могли бы присвоить ей значение, но вы не можете.
Ed Morton
0

Вы можете использовать gsub функция в awk,например, следующая:

 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() предназначен для выполнения нескольких замен, в то время как вы хотите сделать только 1, поэтому вы должны использовать sub() вместо этого 2) первый аргумент для любого из *sub() функции-это регулярное выражение, а не строка, поэтому вы должны использовать регулярное выражение /.../, не строка "...", разделители, 3) вы должны закрепить свое регулярное выражение завершающим $ таким образом, вы удаляете последнее вхождение в строке, а не первое, 4) вам нужно избежать . в регулярном выражении или он будет соответствовать любому символу, а не только . вы хотите соответствовать, 5) вам не нужно grep когда вы используете awk с grep 'cron' | awk '{foo}' = awk '/cron/{foo}'.
Ed Morton

На других языках

Эта страница на других языках

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