преобразовать TXT в файл с колонками - PullRequest
0 голосов
/ 13 января 2019

Мне нужно преобразовать файл test.txt в файл с колонками.

Я знаю, как преобразовать его с помощью awk, если число строк после каждого ключевого слова одинаковое, но в этом примере они разные.

awk 'NR % 5 {printf "%s ", $0; next}1' test.txt 

если число строк здесь одинаковое, это код, но этот не будет работать с этим входным файлом.

В любом случае, чтобы преобразовать это? Пожалуйста, сообщите.

test.txt

"abc"
4
21
22
25
"standard"
1
"test"
4
5
10
11
12

Ожидаемый результат:

"abc" 4 21 22 25
"standard" 1 
"test" 4 5 10 11 12

Ответы [ 5 ]

0 голосов
/ 14 января 2019

Хотя рекомендуется решение awk или sed, поскольку вопрос также помечен bash, вы можете сделать все, что нужно, с помощью простого цикла чтения и переменной флага для управления выводом новой строки для первого итерация. По сути, вы читаете каждую строку и используете индексирование строки расширение параметра , чтобы проверить, является ли первый символ нецифровым, а на 1-й итерации просто выведите строку, для всех дополнительных итераций выведите строку предшествует '\n'. Если строка начинается с цифры, просто выведите ее с пробелом, предшествующим.

Например:

#!/bin/bash

declare -i n=0          ## simple flag to omit '\n' on first string output

while read -r line; do  ## read each line
    [[ ${line:0:1} =~ [^0-9] ]] && {    ## begins with non-digit
        ## 1st iteration, just output $line, rest output '\n$line'
        ((n == 0)) && printf "%s" "$line" || printf "\n%s" "$line"
    } || printf " %s" "$line"   ## begins with digit - output " $line"
    n=1     ## set flag
done < "$1"
echo ""     ## tidy up with newline

Пример использования / Вывод

$ bash fmtlines test.txt
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12

Хотя awk и sed, как правило, будут быстрее (как правило), здесь без всего лишь цикла while read и нескольких условных выражений и расширений параметров, нативное решение bash не будет плохим по сравнению .

Посмотрите вещи и дайте мне знать, если у вас есть вопросы.

0 голосов
/ 14 января 2019
$ awk '{printf "%s%s", (/^"/ ? ors : OFS), $0; ors=ORS} END{print ""}' file
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12
0 голосов
/ 13 января 2019

POSIX awk:

$ awk '/^"/{if (s) print s; s=$0; next} {s=s OFS $0} END{print s}' file
"abc" 4 21 22 25 
"standard" 1 
"test" 4 5 10 11 12 

Или с perl:

$ perl -0777 -lnE 'for (/^"[^"]+"\R(?:[\s\S]+?)(?=^"|\z)/mg) {tr /\n/ /; say} ' file

Если в ваших полях нет пробелов, вы можете использовать простой tr и sed pipe:

$ cat file | tr '\n' ' ' | sed -E 's/ ("[^"]*")/\
\1/g' 

Или GNU sed:

$ cat file | tr '\n' ' ' | sed -E 's/ ("[^"]*")/\n\1/g'
0 голосов
/ 13 января 2019

с GNU awk

$ awk -v RS='\n"' '{$1=$1; printf "%s", rt $0; rt=RT}' file
"abc" 4 21 22 25
"standard" 1
"test" 4 5 10 11 12
0 голосов
/ 13 января 2019

Немного магии, но работает в этом случае:

sed -z 's/\n"/\n\x01"/g' |
tr '\n' ' ' |
tr $'\x01' '\n'
  1. Каждый заголовок начинается с строки " ... ". Итак:
  2. Используя sed Я поместил некоторый разделитель (я выбрал 0x01 в шестнадцатеричном формате) между новой строкой и ", везде в файле. Обратите внимание, что -z является расширением GNU.
  3. Затем я заменяю все символы новой строки пробелом.
  4. Затем я заменяю все 0x01 байтов на новые строки.

Этот метод немного сложен, но прост и работает в случаях, когда заголовок начинается с некоторого определенного символа в начале строки.

Live версия доступна на tutorialspoint .

Можно получить с sed без расширения GNU, используя, например:

sed '2,$s/^"/\x01"/'

т. для строк больше второй, если строка начинается с ", затем добавьте байт 0x01 в начало строки.

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