Как я могу выводить строки с завершающим нулем в Awk?

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

К сожалению, из основной документации awk я не понимаю, как сказать awk, чтобы напечатать строку, завершенную нулем ASCII вместо новой строки. Как я могу сказать awk, что я хочу строки с нулевым завершением?


Версии awk, которые могут быть использованы:

[[email protected]]$ awk --version
awk version 20070501

[[email protected]]$ awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan

[[email protected]]$ awk -W version
GNU Awk 3.1.7

В значительной степени это семейство версий awk. Если нам нужно консолидироваться в версии, это, вероятно, будет GNU Awk, но ответы на все версии приветствуются, так как мне, возможно, придется работать над всеми этими awks. О, устаревшие скрипты.

Ответ 1

Хорошо, у меня это есть.

awk '{printf "%s\0", $0}'

Или, используя ORS,

awk -vORS=$'\0' //

Ответ 2

Существует три варианта:

  • Установка ORS в ASCII ноль: Другие решения имеют awk -vORS=$'\0', но:
    $'\0' является конструкцией, специфичной для некоторых оболочек (bash, zsh).
    Итак: эта команда awk -vORS=$'\0' не будет работать в большинстве старых оболочек.

Существует возможность записать его как: awk 'BEGIN { ORS = "\0" } ; { print $0 }', но это не будет работать с большинством версий awk.

  1. Печать (printf) с символом \0: awk '{printf( "%s\0", $0)}'

  2. Печать непосредственно ASCII 0: awk '{ printf( "%s%c", $0, 0 )}'

Тестирование всех альтернатив с помощью этого кода:

#!/bin/bash

test1(){   # '{printf( "%s%c",$0,0)}'|
    a='awk,mawk,original-awk,busybox awk'
    IFS=',' read -ra line <<<"$a"
    for i in "${line[@]}"; do
        printf "%14.12s %40s" "$i" "$1"
        echo -ne "a\nb\nc\n" |
        $i "$1"|
        od -cAn;
    done
}

#test1 '{print}'
test1 'BEGIN { ORS = "\0" } ; { print $0 }'
test1 '{ printf "%s\0", $0}'
test1 '{ printf( "%s%c", $0, 0 )}'

Получаем следующие результаты:

            awk      BEGIN { ORS = "\0" } ; { print $0 }   a  \0   b  \0   c  \0
           mawk      BEGIN { ORS = "\0" } ; { print $0 }   a   b   c
   original-awk      BEGIN { ORS = "\0" } ; { print $0 }   a   b   c
    busybox awk      BEGIN { ORS = "\0" } ; { print $0 }   a   b   c
            awk                     { printf "%s\0", $0}   a  \0   b  \0   c  \0
           mawk                     { printf "%s\0", $0}   a   b   c
   original-awk                     { printf "%s\0", $0}   a   b   c
    busybox awk                     { printf "%s\0", $0}   a   b   c
            awk               { printf( "%s%c", $0, 0 )}   a  \0   b  \0   c  \0
           mawk               { printf( "%s%c", $0, 0 )}   a  \0   b  \0   c  \0
   original-awk               { printf( "%s%c", $0, 0 )}   a  \0   b  \0   c  \0
    busybox awk               { printf( "%s%c", $0, 0 )}   a   b   c

Как видно из вышеизложенного, первые два решения работают только в GNU AWK.

Наиболее портативным является третье решение: '{ printf( "%s%c", $0, 0 )}'.

Никакое решение не работает правильно в "busybox awk".

Версии, используемые для этих тестов, были следующими:

          awk> GNU Awk 4.0.1
         mawk> mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
 original-awk> awk version 20110810
      busybox> BusyBox v1.20.2 (Debian 1:1.20.0-7) multi-call binary.

Ответ 3

Вы также можете подключить свой выход awk через tr:

awk '{...code...}' infile | tr '\n' '\0' > outfile

Просто протестированный, он работает, по крайней мере, на Linux и FreeBSD.

Если вы не можете использовать новые строки как разделители (например, если выходные записи могут содержать строки новой строки внутри), просто используйте какой-либо другой символ, который гарантированно не появится внутри записи, например. один с кодом 1:

awk 'BEGIN { ORS="\001" } {...code...}' | tr '\001' '\0'

Ответ 4

Я решил распечатать ASCII 0 из awk. Я использую команду UNIX printf "\ 000"

echo | awk -v s='printf "\000"' '{system(s);}'