Обработка текста Точно выходной файл

Мне сделали текстовый файл из вывода инструмента управления репозитория aptly, который перечисляет мои опубликованные репозитории, из которых я должен извлечь информацию.

Формат файла следующие:

Published repositories:
 * test_repo_one/xenial [i386,amd64] publishes {main: [xenial-main_20190311]: Snapshot from mirror [xenial-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {multiverse: [xenial-multiverse_20190311]: Snapshot from mirror [xenial-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {restricted: [xenial-restricted_20190311]: Snapshot from mirror [xenial-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {universe: [xenial-universe_20190311]: Snapshot from mirror [xenial-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}
 * test_repo_one/xenial-security [i386,amd64] publishes {main: [xenial-security-main_20190311]: Snapshot from mirror [xenial-security-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {multiverse: [xenial-security-multiverse_20190311]: Snapshot from mirror [xenial-security-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {restricted: [xenial-security-restricted_20190311]: Snapshot from mirror [xenial-security-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {universe: [xenial-security-universe_20190311]: Snapshot from mirror [xenial-security-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}
 * test_repo_two/trusty [i386,amd64] publishes {main: [trusty-main_20190312]: Snapshot from mirror [trusty-main]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {multiverse: [trusty-multiverse_20190312]: Snapshot from mirror [trusty-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {restricted: [trusty-restricted_20190312]: Snapshot from mirror [trusty-restricted]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {universe: [trusty-universe_20190312]: Snapshot from mirror [trusty-universe]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}
...

Последняя строка вывода заканчивается в новой строке.

"Опубликованные репозитории": строка не требуется.

Для каждого запуска строк '*' я должен удалить постороннюю информацию, уезжать только создает снимки имена. Нет никакого способа выполнить в этом aptly. Желаемый вывод для первой из этих строк.

test_repo_one/xenial [xenial-main_20190311] [xenial-multiverse_20190311] [xenial-restricted_20190311] [xenial-universe_20190311]

Квадратные скобки не важны или так решение, которое сохраняет или удаляет, они прекрасны. Я предпочел бы a sed или awk решение, но что-либо, что работает, высоко ценилось бы.

5
задан 22 March 2019 в 05:51

3 ответа

Подход Perl:

$ perl -lne 'next unless /^\s*\*\s*(\S+)/; $n=$1; @k=(/\{.+?:\s*\[(.+?)\]/g); print "$n @k"' file 
test_repo_one/xenial xenial-main_20190311 xenial-multiverse_20190311 xenial-restricted_20190311 xenial-universe_20190311
test_repo_one/xenial-security xenial-security-main_20190311 xenial-security-multiverse_20190311 xenial-security-restricted_20190311 xenial-security-universe_20190311
test_repo_two/trusty trusty-main_20190312 trusty-multiverse_20190312 trusty-restricted_20190312 trusty-universe_20190312

Объяснение

  • perl -lne: считайте входной файл линию за линией (-n), удалите запаздывание новых строк (-l) и запущенный скрипт, данный -e на каждой строке. -l также добавляет новую строку к каждому print звонить.
  • next unless /^\s*\*\s*(\S+)/; : найдите название repo, таким образом, первый фрагмент непробельных символов (\S+) на строке, которая запускается с 0 или больше пробельных символов (^\s*), затем a * (\*), и 0 или больше пробельных символов снова. Самый длинный фрагмент непробела после этого - то, что мы хотим. Если эта строка не соответствует этому regex, next перейдет нас на следующую строку.
  • $n=$1 : сохраните то, что было получено соответствием выше ( (\S+) в круглых скобках, $1) как $n.
  • @k=(/\{.+?:\s*\[(.+?)\]/g): найдите все случаи, где у нас есть a {, любые другие символы и затем a :, сопровождаемый пробелом и a [ и получите что-либо между [ и ]. Сохраните все соответствующие строки в массиве @k.
  • print "$n @k" : наконец, распечатайте название repo, $n, и массив @k сверху.

Если Вы предпочитаете включать квадратные скобки, можно использовать:

$ perl -lne 'next unless /^\s*\*\s*(\S+)/; $n=$1; @k=(/\{.+?:\s*(\[.+?\])/g); print "$n @k"' file 
test_repo_one/xenial [xenial-main_20190311] [xenial-multiverse_20190311] [xenial-restricted_20190311] [xenial-universe_20190311]
test_repo_one/xenial-security [xenial-security-main_20190311] [xenial-security-multiverse_20190311] [xenial-security-restricted_20190311] [xenial-security-universe_20190311]
test_repo_two/trusty [trusty-main_20190312] [trusty-multiverse_20190312] [trusty-restricted_20190312] [trusty-universe_20190312]
3
ответ дан 23 November 2019 в 08:58

Два ответа в одном

Я отправил два ответа здесь:

  • Сценарий удара, который, надо надеяться, легче понять
  • Острота с помощью общих утилит Linux grep, sed и cut

Как сценарий Bash смотрит в операции

Я выключил терминальную гномом строку, переносятся для создания входных и выходных файлов легче читать.

───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/askubuntu$ tput rmam # Turn off line wrap
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/askubuntu$ cat aptfilein
Published repositories:
 * test_repo_one/xenial [i386,amd64] publishes {main: [xenial-main_20190311]: Snapshot from mirr}
 * test_repo_one/xenial-security [i386,amd64] publishes {main: [xenial-security-main_20190311]: }
 * test_repo_two/trusty [i386,amd64] publishes {main: [trusty-main_20190312]: Snapshot from mirr}
...
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/askubuntu$ time aptfileparse.sh
5 lines read from aptfilein
3 lines written to aptfileout

real    0m0.025s
user    0m0.016s
sys     0m0.004s
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/askubuntu$ cat aptfileout
 test_repo_one/xenial [xenial-main_20190311] [xenial-multiverse_20190311] [xenial-restricted_201]
 test_repo_one/xenial-security [xenial-security-main_20190311] [xenial-security-multiverse_20190]
 test_repo_two/trusty [trusty-main_20190312] [trusty-multiverse_20190312] [trusty-restricted_201]
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/askubuntu$ 

Фактический сценарий Bash

Не забудьте делать исполняемый файл сценария с chmod a+x script.sh

#!/bin/bash

# NAME: aptfileparse.sh
# PATH: ~/askubuntu
# DESC: Parse Apt File giving new lines.
# DATE: July 1, 2019.
# NOTE: For: https://askubuntu.com/questions/1127821/text-processing-aptly-output-file
#       Program would be ~10 lines shorter (but harder to read) with arrays.

: <<'END'
/* -----------------------------------------------------------------------------

INPUT FILE LAYOUT
=================

Published repositories:
 * test_repo_one/xenial [i386,amd64] publishes {main: [xenial-main_20190311]: Snapshot from mirror [xenial-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {multiverse: [xenial-multiverse_20190311]: Snapshot from mirror [xenial-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {restricted: [xenial-restricted_20190311]: Snapshot from mirror [xenial-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {universe: [xenial-universe_20190311]: Snapshot from mirror [xenial-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}
 * test_repo_one/xenial-security [i386,amd64] publishes {main: [xenial-security-main_20190311]: Snapshot from mirror [xenial-security-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {multiverse: [xenial-security-multiverse_20190311]: Snapshot from mirror [xenial-security-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {restricted: [xenial-security-restricted_20190311]: Snapshot from mirror [xenial-security-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {universe: [xenial-security-universe_20190311]: Snapshot from mirror [xenial-security-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}
 * test_repo_two/trusty [i386,amd64] publishes {main: [trusty-main_20190312]: Snapshot from mirror [trusty-main]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {multiverse: [trusty-multiverse_20190312]: Snapshot from mirror [trusty-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {restricted: [trusty-restricted_20190312]: Snapshot from mirror [trusty-restricted]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {universe: [trusty-universe_20190312]: Snapshot from mirror [trusty-universe]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}
...

OUTPUT FILE LAYOUT
==================

 test_repo_one/xenial [xenial-main_20190311] [xenial-multiverse_20190311] [xenial-restricted_20190311] [xenial-universe_20190311]

Five fields to extract: name, main, multiverse, restricted, universe

----------------------------------------------------------------------------- */
END

 INPUT="aptfilein"
OUTPUT="aptfileout"

> "$OUTPUT" # Erase previous output file

# Read all input lines
while IFS= read -r line ; do

    let CountIn++
    ! [[ "$line" =~ " *" ]] && continue     # skip lines not starting " *"
    # Get name
    line="${line#" * "}"                    # remove leading " * "
    lout="${line%%" "*}"                    # name is up to next " "
    line="${line#" "*}"                     # remove name from line
    # Get main
    line="${line#*"{main: "}"               # remove leading "{main: "
    lout="$lout ${line%%":"*}"              # main is up to next ":"
    line="${line#":"*}"                     # remove name from line
    # Get multiverse
    line="${line#*"{multiverse: "}"         # remove leading "{multiverse: "
    lout="$lout ${line%%":"*}"              # maultiverse is up to next ":"
    line="${line#":"*}"                     # remove multiverse from line
    # Get restricted
    line="${line#*"{restricted: "}"         # remove leading "{restricted: "
    lout="$lout ${line%%":"*}"              # restricted is up to next ":"
    line="${line#":"*}"                     # remove restricted from line
    # Get universe
    line="${line#*"{universe: "}"           # remove leading "{universe: "
    lout="$lout ${line%%":"*}"              # universe is up to next ":"
    line="${line#":"*}"                     # remove universe from line

    # Append line to output file with leading space
    echo " $lout" >> "$OUTPUT"
    let CountOut++

done < "$INPUT"

echo  "$CountIn lines read from $INPUT"
echo "$CountOut lines written to $OUTPUT"

Острота с общими утилитами

Остроты популярны в сообществе Linux и существуют некоторые превосходные awk и perl ответы отправляются в этом Вопросы и ответы. Вот пример с помощью общих утилит, с которыми большинство опытных пользователей командной строки знакомо:

$ time grep ^" \*" aptfilein | sed 's/ \* //;s/ /: /;s/^/ /' | cut -d':' -f1,3,6,9,12 --output-delimiter=''
 test_repo_one/xenial [xenial-main_20190311] [xenial-multiverse_20190311] [xenial-restricted_20190311] [xenial-universe_20190311]
 test_repo_one/xenial-security [xenial-security-main_20190311] [xenial-security-multiverse_20190311] [xenial-security-restricted_20190311] [xenial-security-universe_20190311]
 test_repo_two/trusty [trusty-main_20190312] [trusty-multiverse_20190312] [trusty-restricted_20190312] [trusty-universe_20190312]

real    0m0.011s
user    0m0.003s
sys     0m0.008s
  • grep ^" \*" aptfilein - grep команда выбирает строки, содержащие строку поиска. Морковь (^) обозначает, что строка должна запуститься в начале строки. Обратная косая черта (\) обозначает звездочку/нащельную рейку (*) должен быть взят буквально и не действие как подстановочный символ, который выбирает все. Таким образом, это grep команда выбирает все начало строк * в файле aptfilein.
  • sed "потоковый редактор", который редактирует входящие строки и изменяет их и раздает их. Существуют три sed изменения здесь 's/ \* //;s/ /: /;s/^/ /'. Изменения между кавычками (') и очерченный (разделенный) точкой с запятой (;) deliminator. Они сломаны на следующие три точки.
  • s/ \* // - поисковое первое вхождение * и измените его на пустой указатель. Это сотрется * это начинается в каждой строке.
  • s/ /: / - поиски первого пространства и изменений это в двоеточие (:) сопровождаемый пространством. Это необходимо для изменения нашего первого поля в ключ. Например, test_repo_one/xenial становится test_repo_one/xenial:.
  • s/^/ / - говорит sed вставлять пробел в начале каждой строки.
  • cut -d':' -f1,3,6,9,12 --output-delimiter='' - Использование cut управляйте для выбора полей ключа № 1, 3, 6, 9 и 12. Поля ключа разграничены двоеточием как аргумент -d':' предусматривает. Обычно выходные поля разграничены то же, но это переопределяется к использованию пустого указателя - выходной разделитель ='' параметр.

Примечание: Острота быстрее, чем удар, который медленнее при строковой обработке.

3
ответ дан 23 November 2019 в 08:58

Мой подход awk:

$ cat 1.txt 
Published repositories:
 * test_repo_one/xenial [i386,amd64] publishes {main: [xenial-main_20190311]: Snapshot from mirror [xenial-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {multiverse: [xenial-multiverse_20190311]: Snapshot from mirror [xenial-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {restricted: [xenial-restricted_20190311]: Snapshot from mirror [xenial-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}, {universe: [xenial-universe_20190311]: Snapshot from mirror [xenial-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial [src]}
 * test_repo_one/xenial-security [i386,amd64] publishes {main: [xenial-security-main_20190311]: Snapshot from mirror [xenial-security-main]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {multiverse: [xenial-security-multiverse_20190311]: Snapshot from mirror [xenial-security-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {restricted: [xenial-security-restricted_20190311]: Snapshot from mirror [xenial-security-restricted]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}, {universe: [xenial-security-universe_20190311]: Snapshot from mirror [xenial-security-universe]: http//gb.archive.ubuntu.com/ubuntu/ xenial-security[src]}
 * test_repo_two/trusty [i386,amd64] publishes {main: [trusty-main_20190312]: Snapshot from mirror [trusty-main]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {multiverse: [trusty-multiverse_20190312]: Snapshot from mirror [trusty-multiverse]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {restricted: [trusty-restricted_20190312]: Snapshot from mirror [trusty-restricted]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}, {universe: [trusty-universe_20190312]: Snapshot from mirror [trusty-universe]: http//gb.archive.ubuntu.com/ubuntu/ trusty[src]}

$ awk '$1=="*"{split ($0, a, /:/); print $2 a[2] a[5] a[8] a[11]}' 1.txt 
test_repo_one/xenial [xenial-main_20190311] [xenial-multiverse_20190311] [xenial-restricted_20190311] [xenial-universe_20190311]
test_repo_one/xenial-security [xenial-security-main_20190311] [xenial-security-multiverse_20190311] [xenial-security-restricted_20190311] [xenial-security-universe_20190311]
test_repo_two/trusty [trusty-main_20190312] [trusty-multiverse_20190312] [trusty-restricted_20190312] [trusty-universe_20190312]
2
ответ дан 23 November 2019 в 08:58

Другие вопросы по тегам:

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