форматирование файла с использованием awk

Я столкнулся с этой проблемой, используя Docker и Centos 7. В итоге я сделал следующее:

yum install -y sudo

sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers

Я нашел этот хак на https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile

0
24.04.2019, 19:08
5 ответов
$ sed -e 's/|/","/g' -e 's/=/"="/g' -e 's/\t/\t"/' -e 's/$/"/' input.txt

Это будет:

  • заменить любой |на,
  • заменить любой =на"="
  • заменить первую позицию табуляции на\t"
  • добавить "и конец строки

Самый простой способ с awk— перейти на разделители полей:

$ awk -v FS="|" -v OFS='","' '{$1=$1}1' \
  | awk -v FS="=" -v OFS='"="' '{$1=$1}1'\
  | awk -v FS="\t" '{print $1,"\""$2"\""}' input.txt
1
28.01.2020, 03:47

Использование sed:

sed -e 's/|/","/g;s/=/"="/g;s/ /"/4;s/$/"/g' file

1503668542862176   "manager"="10001","Bounced"="999","Analyst"="10004","Business Analyst"="10005","Programmer"="10003"
1552024948590636   "manager"="10001","Bounced"="999","Analyst"="10004"
1551728916565460   "Bounced"="999","Analyst"="10004"
1553617087089790   "Analyst"="10004"
1538058487418963   "manager"="10001","Architect"="10002","Analyst"="10004"
0
28.01.2020, 03:47

Если вы можете использовать GNU awk (, который обычно доступен в любом стандартном дистрибутиве Linux ), вы можете использовать выражения sub -с функцией gensub() :

< input_data awk -- '{gsub("\\|", ","); print gensub("([[:alpha:]][^=]*)=([^,]+)", "\"\\1\"=\"\\2\"", "g")}'

Предположим, что |появляется только как разделитель пар ключей -и значений -, первый gsub()преобразует каждый |в ,, а затем функция gensub()делает все остальное.

Если вы должны использовать POSIX awk, вы все равно можете получить то же самое с помощью одного скрипта, используя последовательность (действительно неудобно..)gsub()s:

< input_data awk -- '{gsub("=", "\""); gsub("([[:alpha:]][^\"]*)", "\"&\"="); gsub("\"[^|]*", "&\""); gsub("\\|", ","); print;}'

Разобрано (только awkчасть скрипта):

{
    gsub("=", "\"");
    gsub("([[:alpha:]][^\"]*)", "\"&\"=");
    gsub("\"[^|]*", "&\"");
    gsub("\\|", ",");
    print;
}

Первый gsub()заменяет каждый =на ", прокладывая путь для последующей пары gsub()с, первый ищет ключи до (, но исключает )первый "и заменив всю эту строку начальным "плюс найденный ключ плюс конечный "=, а второй gsub()ищет значения, начинающиеся с "(, которые первоначально были=)до (. ] но исключая )первый|(если он присутствует )и заменяя эту строку самой собой плюс конечный ".

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

Окончательное решение gsub()заменяет все |в ,так же, как и в первом решении.

0
28.01.2020, 03:47

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

BEGIN {
    # Assume the two fields are tab-delimited.
    OFS = FS = "\t"
}

NF > 1 {
    # Split the 2nd field into sub-fields on "|" in the array a.
    n = split($2, a, "|")

    for (i = 1; i <= n; ++i)
        # Split each sub-field on "=" and quote the two bits,
        # and put them together again.
        if (split(a[i], b, "=") == 2)
            a[i] = sprintf("\"%s\"=\"%s\"", b[1], b[2])
        else {
            # Bail out on bad fields.
            print >"/dev/stderr"
            printf("Error in field %d on line %d\n", i, FNR) >"/dev/stderr"
            exit 1
        }

    # Reconstruct current record.
    $0 = $1
    $2 = a[1]

    for (i = 2; i <= n; ++i)
        $2 = $2 "," a[i]

    # Done, output
    print
}

Тестирование:

$ awk -f script.awk file
1503668542862176        "manager"="10001","Bounced"="999","Analyst"="10004","Business Analyst"="10005","Programmer"="10003"
1552024948590636        "manager"="10001","Bounced"="999","Analyst"="10004"
1551728916565460        "Bounced"="999","Analyst"="10004"
1553617087089790        "Analyst"="10004"
1538058487418963        "manager"="10001","Architect"="10002","Analyst"="10004"
0
28.01.2020, 03:47

Выполнено командой awk

команда:

awk '{gsub(/\|/,",",$0);print $0}' filename | awk '{$2="\""$2;print $0}'| awk '{gsub(/\=/,"\"=\"",$0);print $0}'| awk '{gsub(/\,/,"\",\"",$0);print $0}'| awk '{$NF=$NF"\"";print $0}'

выход

 awk '{gsub(/\|/,",",$0);print $0}' filename| awk '{$2="\""$2;print $0}'| awk '{gsub(/\=/,"\"=\"",$0);print $0}'| awk '{gsub(/\,/,"\",\"",$0);print $0}'| awk '{$NF=$NF"\"";print $0}'

1503668542862176 "manager"="10001","Bounced"="999","Analyst"="10004","Business Analyst"="10005","Programmer"="10003"
1552024948590636 "manager"="10001","Bounced"="999","Analyst"="10004"
1551728916565460 "Bounced"="999","Analyst"="10004"
1553617087089790 "Analyst"="10004"
1538058487418963 "manager"="10001","Architect"="10002","Analyst"="10004"
-1
28.01.2020, 03:47

Теги

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