awk: вывести последние N столбцов, но с другим разделителем полей

На моей не -настройке luks lvm с этой схемой

NAME           MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda              8:0    0 978.1G  0 disk 
├─sda1           8:1    0   260M  0 part /boot/efi
└─sda2           8:2    0 977.9G  0 part 
  ├─vtb-Kali   253:0    0    50G  0 lvm  /
  ├─vtb-Bunsen 253:1    0    10G  0 lvm  
  ├─vtb-Home   253:2    0   200G  0 lvm  /home
  └─vtb-Work   253:3    0   300G  0 lvm  /home/bu5hman/Documents/work

Моя последовательность загрузки GRUB для тех радостных случаев, когда GRUBдает сплат,

set root=(/lvm/vtb-Kali)
linux /vmlinuz root=/dev/mapper/vtb-Kali
initrd /initrd.img
boot

Судя по этому, вы указываете set rootне на тот раздел.

Поверить Fedora за установку рута на /на вашем lvm и оставить fstab для выбора /boot/efiЯ бы посоветовал вам попробовать

set root=(/lvm/fedora_unix-03)
linuxefi  /vmlinuz-4.17.2-200.fc28.x86_64  root=/dev/mapper/fedora_unix-03
initrdefi /initramfs-4.17.2-200.fc28.x86_64.img
boot

Если это не сработает, попробуйте без ведущего /вset root

set root=(lvm/fedora_unix-03)

РЕДАКТИРОВАТЬ :после обсуждения в комментариях

попробуй

`set root=`  with either of the 2 options in my previous post.

После вызова linuxefi используйте

root=/dev/mapper/luks-d2c9decd-e486-4ef3-9146-654ca2b4ec0a
1
10.04.2020, 19:00
6 ответов

Используйте тернарный оператор, чтобы выбрать правильный разделитель:

echo "DOWN_COMP_002_wget_001_6_2020-04-10-13_40_27_395533885" | 
    awk 'BEGIN{FS="_|-"} {for(i=6;i<=NF;i++) printf $i (i < NF ? "::" : "\n")}'

Выход:

6::2020::04::10::13::40::27::395533885
2
19.03.2021, 02:30

В данном конкретном случае, вероятно, проще использовать cutвместо awk, а затем sedдля изменения разделителя:

$ echo "DOWN_COMP_002_wget_001_6_2020-04-10-13_40_27_395533885" | 
    cut -d_ -f6- | sed 's/_/::/g'
6::2020-04-10-13::40::27::395533885

Я предпочитаю это, поскольку для получения последних N полей в awk требуется громоздкий цикл for, а cutподдерживает формат N-для «последних N».

Если вам абсолютно необходимо использовать awk, вы можете попробовать:

$ echo "DOWN_COMP_002_wget_001_6_2020-04-10-13_40_27_395533885" | 
    awk -F"_" '{for(i=6;i<=NF-1;i++){printf "%s::",$i} print $NF}'
6::2020-04-10-13::40::27::395533885

Или, если вы хотите использовать -в качестве разделителя, попробуйте:

$ echo "DOWN_COMP_002_wget_001_6_2020-04-10-13_40_27_395533885" | 
    awk -F"[-_]" '{for(i=6;i<=NF-1;i++){printf "%s::",$i} print $NF}'
6::2020::04::10::13::40::27::395533885
6
19.03.2021, 02:30

С (ГНУ)sed:

echo "DOWN_COMP_002_wget_001_6_2020-04-10-13_40_27_395533885" | sed 's/_/::/6g'
DOWN_COMP_002_wget_001_6::2020-04-10-13::40::27::395533885

Обратите внимание info sedна эту конструкцию:

The 's' command can be followed by zero or more of the following FLAGS:

'g'

Apply the replacement to _all_ matches to the REGEXP, not just the first.

'NUMBER'

Only replace the NUMBERth match of the REGEXP. 

interaction in 's' command Note: the POSIX standard does not specify what should happen
when you mix the 'g' and NUMBER modifiers, and currently there is no widely agreed upon
meaning across 'sed' implementations.  For GNU 'sed', the interaction is defined to be:
ignore matches before the NUMBERth, and then match and replace all matches from the NUMBERth on.
4
19.03.2021, 02:30

другой awkвариант:

awk -F'[_-]' -v col=7 '{ 
    while (col-->0) { printf "%s%s", $(NF-col), (col? "::" : ORS) };
}' infile

отрегулируйте col=Nс помощью " количества N последних столбцов ", которые вы хотите напечатать.


Ответ на исправленный вопрос:

So is there a away to generate print print $1,$3,$5.... programitcally so that OFS is automatically used

лично, а также технически нет причин ограничиваться использованием ОФС , но ладно, если хотите, вот как это сделать:

awk -F'[_-]' -v c=col=7 '{
    while (col-->0) { printf "%s%s", $(NF-col), (col? XXX : ORS) };
}' XXX='::' infile

а знаете что там за OFS? замените все XXXвыше на OFS; теперь удалите XXX='::'и замените XXXпросто "::"; ну так почему же тогда застряли на использовании OFS?

2
19.03.2021, 02:30
$ echo "DOWN_COMP_002_wget_001_6_2020-04-10-13_40_27_395533885" |
    awk -v n=7 -F'[_-]' -v OFS='::' 'NF>n{sub("([^_-]*[_-]){"NF-n"}","")} {$1=$1} 1'
2020::04::10::13::40::27::395533885
1
19.03.2021, 02:30

Я интерпретирую ваш вопрос «Как сделать вывод с помощью OFS» так как вы хотите выполнить одно printбез аргументов и позволить awkавтоматически вставить новый разделитель полей между полями.

Для этого придется перестроить $0, т.е. текущую запись. Вы можете легко сделать это, сначала установив $0в пустую строку, а затем назначив полям.

Поскольку вы очищаете текущую запись, вам придется хранить данные, которые будут возвращены в нее, в массиве.

Ниже приведен пример того, как это можно сделать.:

echo 'DOWN_COMP_002_wget_001_6_2020-04-10-13_40_27_395533885' |
awk -F '[-_]' '
        BEGIN { OFS = "::" }
        {
                nf = 0

                # save the last seven fields in "field"
                for (i = NF - 6; i <= NF; ++i)
                        field[++nf] = $i

                # clear record
                $0 = ""

                # reassign data into record
                for (i = 1; i <= nf; ++i)
                        $i = field[i]

                # output record
                print
        }'

Этот код выводит

2020::04::10::13::40::27::395533885

И он делает это, сохраняя данные, которые должны быть частью выходной записи в массиве field, очищая текущую запись с помощью $0 = "", а затем присваивая сохраненные данные записи перед печатью.

3
19.03.2021, 02:30

Теги

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