awk :Создать новую запись и обновить NR

Если у вас есть root-доступ к серверу и вы можете восстановить ssh-ключи для своих пользователей на случай их потери

И

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

И

им никогда никогда не понадобится «физический» (через клавиатуру+монитор или через удаленную консоль для ВМ )доступ к серверу

И

нет пользователей с паролем -закрытый sudoдоступ (т.е. они либо вообще не имеют доступа к sudo, либо имеют доступ к sudo сNOPASSWD)

Я думаю, ты поправишься.

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

3
08.06.2021, 15:47
2 ответа

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

awk '
    {
        print $0
        magic to create a new record with contents "Foo"
    }
'

напечатает исходную запись, а затем войдет в бесконечный цикл, выводящий «Foo», потому что по определению awk выполняет приведенный выше код один раз для каждой входной записи.

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

awk '
    {
        prt($0)
        other stuff
        prt("Foo")
    }
    function prt(str) {
        print str
    }
'

но это не то же самое, что создание новой входной записи.

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

Однако вы перегружаете/злоупотребляете значением NR. NR— это количество прочитанных входных записей, вы пытаетесь напечатать количество выходных записей, что является совершенно другим. Для этого нет встроенной переменной, поскольку тривиально просто отслеживать ее самостоятельно в отдельной переменной, а не возиться с NR, например. с onrниже:

$ cat file
awk '
    BEGIN { print "NR", "onr", "line" }
    NR == 1 { val = $2-1 }
    {
        for (val++; val<$2; val++) {
            processString($1 FS val)
        }
        processString($0)
    }

    function processString(str) {
        print NR, ++onr, str
    }
' file
NR onr line
1 1 entry 13
2 2 entry 14
2 3 entry 15
3 4 entry 16
3 5 entry 17
3 6 entry 18

Опять же, -мы НЕ создаем новые входные записи, поэтому(как всегда)было бы совершенно неуместно пытаться настроить значение встроенной переменной NR. Вместо этого мы просто генерируем новые выходные записи и отслеживаем общее количество выходных записей в определенной пользователем -переменной с именем onr.

Я добавил как NR, так и onrк выходу и изменил входной пример на:

$ cat file
entry 13
entry 15
entry 18

, чтобы подчеркнуть, что на самом деле в игре есть 3 отдельных элемента данных:

  1. NR= количество входных записей,
  2. onr= количество выходных записей,
  3. val= значение $2, которое будет напечатано для каждой записи

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

3
28.07.2021, 11:26

РЕДАКТИРОВАТЬ + Предупреждение

Как указано в комментариях ниже, NRи FNRявляются по определению счетчиками для входных записей и поэтому должны оставаться нетронутыми. (Ref:gawk manual)Не манипулируйте этими значениями, как предлагается ниже, несмотря на возможность делать это без ограничений! Я оставлю этот ответ как предупреждение.


Хорошо, благодаря комментариям Джеффа Шаллера, Ромео Нинова и фра -сан, работают следующие подходы:

  • увеличение вручную NRилиFNR
  • использовать правильно определенный цикл с NR/FNR

Возможный скрипт:

awk 'BEGIN {print "NR","line"}
     $2 > NR { for (NR; NR<$2; NR++) print NR,"entry "NR }
     {print NR,$0}' infile

Замените NRна FNR, чтобы обеспечить правильную нумерацию в случае нескольких входных файлов (и, возможно, по-прежнему используйте NR++, чтобы обеспечить правильное общее число ).

Тем самым NR++имитирует обновление NR,в то время как цикл имитирует повторные команды для той же записи (псевдо-напротив оператора next), что в целом делает его похожим на вновь созданную запись с соответствиемNR(FNR).

2
28.07.2021, 11:26

Теги

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