Редактировать строку после совпадающего шаблона

Это кажется простой задачей для SQL.

csv+ sql== csvsqlизcsvkit!

Вы можете установить его через pip.

Прежде чем вы сможете начать, вам может потребоваться исправить файл перед выполнением этого :Удалите пустую строку и пробелы в конце каждой строки:

sed -i.bak '2d;s/[[:blank:]]*$//' file

Вы можете пройти половину пути с помощью:

csvsql \
    -d' ' -S \
    --query 'select cable,grnd_sta || "-" || chan_pdu,group_concat(fldr) from file group by cable' \
    file \
| csvformat -D' '
  • Вам может понадобиться -tвместо -d' ', если ваш файл разделен табуляцией.
  • Используйте csvformat -D' 'для получения вывода с разделителями -, так как csvsqlвыводит только разделители с запятыми -. С awkработать проще, но csvsql заключит последний столбец в кавычки, а нам это не нужно!

Выход:

cable "grnd_sta || ""-"" || chan_pdu" group_concat(fldr)
1 97-108 79,817,946
3 145-156 64,66,117,240,255,263,291

Отсюда вы можете продолжить использованиеawk:

... \
| awk 'NR>1{printf "Cable %s\n\n%s\n%s\n\n",$1,$2,$3}' \
| head -n-1

Выход:

Cable 1

97-108
79,817,946

Cable 3

145-156
64,66,117,240,255,263,291

0
07.05.2021, 21:39
3 ответа

Существует несколько способов извлечения необходимых данных.

Если вы видите каждую строку как ряд полей, разделенных пробелом, то самый простой инструмент, который вы можете использовать для решения вашей проблемы, будетcut:

$ cut -d ' ' -f 1,2,4,6 file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100

Это извлекает из файла 1-е, 2-е, 4-е и 6-е поля с разделителями -пробелами.

Аналогично, сawk:

$ awk '{ print $1,$2,$4,$6 }' file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100

Это то же самое, но немного больше. Инструмент awkобрабатывает свой ввод как поток записей , состоящих из полей . По умолчанию запись — это просто строка, а поле — любой непустой -текст, разделенный пробелами (пробелами или символами табуляции, возможно более одного ). Вывод создается по одной записи за раз (по умолчанию, по строке за раз ), а поля разделены одним пробелом.


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

$ paste -d ' ' \
    <( cut -d ' ' -f 1  file ) \
    <( cut -d ' ' -f 2- file | tr -s '[:alpha:]' '[ *]' )
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100

Это несколько неэлегантно, потому что ввод считывается дважды. Используемая команда trизменит все буквенные символы на пробелы, а затем «сожмет» (с помощью-s)любой набор из нескольких последовательных пробелов в одиночные пробелы.

Команда pasteполучает два входных потока и объединяет их построчно с пробелом в -между ними. Первый поток обеспечивается заменой процесса (<( ... )), запускающей команду cut, которая извлекает из данных только первый столбец. Второй поток предоставляется другим подстановочным процессом, выполняющим cutдля извлечения всех столбцов, начиная со столбца 2, и который затем заменяет буквенные символы пробелами в этих столбцах, используя tr, как описано выше.

0
28.07.2021, 11:34

Неясно, насколько конкретно ваш пример относится к вашей проблеме. Предполагая, что это буквально то, о чем вы спрашиваете (, что заставляет меня беспокоиться, что это может быть классное упражнение ), тогда вы можете воспользоваться тем фактом, что вам нужно удалить только 3 известные строки и что вы хотите получить только одиночные пробелы между символами, чтобы создать довольно короткую команду sed. В этом примере используется BSD sed, поставляемый с MacOS, ввод осуществляется в файл input.txt, а вывод — в стандартный вывод.

sed -E -e 's/ (minutes|seconds|msec)//g' < input.txt

Это будет соответствовать одному пробелу, за которым следует одна из ваших целевых строк, а затем ничего не заменит. Буква «g» в конце говорит о многократном применении к одной и той же строке.

0
28.07.2021, 11:34

Одним из решений является удаление всех «одного пробела», за которым следуют «не-числовые слова»:

$ sed -E 's/ \<[^0-9]*\>//g' file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100
0
28.07.2021, 11:34

Теги

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