Как вывести строки с нулевым символом в конце в Awk? - PullRequest
14 голосов
/ 03 февраля 2012

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

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


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

[user@server1]$ awk --version
awk version 20070501

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

[user@server3]$ awk -W version
GNU Awk 3.1.7

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

Ответы [ 4 ]

19 голосов
/ 03 февраля 2012

Хорошо, я понял.

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

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

awk -vORS=$'\0' //
14 голосов
/ 31 августа 2015

Есть три варианта:

  1. Установка 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.
4 голосов
/ 18 ноября 2015

Вы также можете передать ваш awk вывод через tr :

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

Только что протестированный, он работает по крайней мере на Linux и FreeBSD.

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

awk 'BEGIN { ORS="\001" } {...code...}' | tr '\001' '\0'
0 голосов
/ 06 июня 2013

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

echo | awk -v s='printf "\000"' '{system(s);}'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...