Как заставить пробел стать входом цикла for?

Ваша проблема в том, что :bash -завершение не понимает псевдонимы. Таким образом, если вы пишете псевдоним, он просто воспринимается как неизвестная команда и не будет автоматически завершен -. Вы можете вернуться к завершению имени файла по умолчанию, если это то, что вы хотите. Или вы можете установить программу, которая расширяет псевдонимы перед автоматическим -завершением и дополняет ваши псевдонимы как их псевдонимы команд.

1
22.06.2021, 06:39
3 ответа

awkодин может сделать все это. Вам не нужна оболочка сценария оболочки, вам, конечно же, не нужно ничего столь вычурного, как cat 20210622_090009.txt | tail -n 26 | cut -f 5 | awk '{print $2}'), и вам следует избегать использования оболочки, в то время как -цикл чтения (или цикл for над выводом языка как awk или perl )везде, где это возможно (см. Почему использование цикла оболочки для обработки текста считается плохой практикой? по причинам, почему ).

Эмпирическое правило :Если вы когда-нибудь обнаружите, что думаете: «Я хочу повторить вывод awk», вы должны изменить свое мнение на «Я почти наверняка должен сделать это только с awk» или оболочкой оболочки, которая настраивает ввод и перенаправление вывода для awk для выполнения массовой обработки. То же самое для Perl и большинства других языков. Любой другой язык справится с обработкой лучше, чем оболочка, и вы только усложните себе работу, пытаясь сделать это с помощью оболочки.

В любом случае, следующий скрипт выводит столбец 4, если столбцов ровно 8(NF == 8). Если столбцов меньше 8 (NF < 8), печатается пустая строка. В обоих случаях он игнорирует две строки заголовков в начале каждого входного файла (, он может обрабатывать один или несколько аргументов имени файла. FNR < 3 {next}. В awk NR — это общее количество прочитанных строк, а FNR — это номер строки текущего файла ).

$ awk 'FNR < 3 {next}; NF == 8 {print $4}; NF < 8 {print ""}' 20210622_090009.txt  
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s

8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s
11
28.07.2021, 11:23

Похоже, у вас поля с фиксированной шириной, поэтому используйте GNU awk для FIELDWIDTHS и gensub():

$ awk -v FIELDWIDTHS='16 12 24 *' '
    NR>2 {
        gsub(/^ *| *$/,"",$3)
        print gensub(/.* ([^ ]+).*/,"\\1",1,$3)
    }
' file
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s

8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s

Вышеприведенное сначала идентифицирует содержимое каждого поля по ширине каждого поля.:

$ cat file
nvmeSerial      Endpoint        nvmeSpeed           nvmeWidth
================================================================================
nvme0n1         c7:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme1n1         c8:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme15n1        48:00.0                             Width x2 (downgraded)
nvme25n1        0a:00.0     Speed 32GT/s (ok)       Width x2 (downgraded)

$ cat tst.awk
BEGIN { FIELDWIDTHS="16 12 24 *" }
NR != 2 {
    print
    for (i=1; i<=NF; i++) {
        gsub(/^ *| *$/,"",$i)
        print "\t" i, "<" $i ">"
    }
    print "-----"
}

$ awk -f tst.awk file
nvmeSerial      Endpoint        nvmeSpeed           nvmeWidth
        1 <nvmeSerial>
        2 <Endpoint>
        3 <nvmeSpeed>
        4 <nvmeWidth>
-----
nvme0n1         c7:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
        1 <nvme0n1>
        2 <c7:00.0>
        3 <Speed 8GT/s (ok)>
        4 <Width x2 (downgraded)>
-----
nvme1n1         c8:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
        1 <nvme1n1>
        2 <c8:00.0>
        3 <Speed 8GT/s (ok)>
        4 <Width x2 (downgraded)>
-----
nvme15n1        48:00.0                             Width x2 (downgraded)
        1 <nvme15n1>
        2 <48:00.0>
        3 <>
        4 <Width x2 (downgraded)>
-----
nvme25n1        0a:00.0     Speed 32GT/s (ok)       Width x2 (downgraded)
        1 <nvme25n1>
        2 <0a:00.0>
        3 <Speed 32GT/s (ok)>
        4 <Width x2 (downgraded)>
-----

а затем достаточно просто выбрать часть третьего поля, которую вы хотите напечатать. например. используя gensub(), как и я. Вышеупомянутое будет работать независимо от того, какие поля отсутствуют в любой строке, сколько слов в любом поле и т. д.

7
28.07.2021, 11:23

Другой метод, предполагающий поля фиксированной ширины (, извлекает только одно из полей и предполагает, что оно всегда начинается с 6 символов «Скорость», если оно не пусто):

cut -c35-52 file | sed '1,2d;s/.*//'

Или сопоставьте " Скорость ":

awk -F ' Speed +' 'NR>2 {sub(/.*/,"",$2); print $2}' file
sed -E '1,2d;s/.* Speed +([^ ]+).*/\1/;t;c\\' file
perl -nE 'say m{\sSpeed\s+(\S+)} if $.>2' file
2
28.07.2021, 11:23

Теги

Похожие вопросы