Портативный способ удалить первую строку из пространства образца (когда несколько строк присутствуют)

Переформатируйте исходный пример для удобства чтения:

join -a1 -e "NoMatch" \
 <(awk -F ' ' '{print $0}' file1.txt |tail -n +2|sort -k1,1) \
 <(cat file2 | sort -k1,1)

Все проблемы связаны с обработкой file2 и с опциями join.

  1. file2 сортируется по полю 1, а должно быть по полю 2.
  2. Отсутствует опция -t '' для join, файл2 разделен табуляцией.
  3. Отсутствует опция join для объединения по полю 2 файла2.
  4. Даже при правильном поле join для файла2, вывод по умолчанию печатает сначала поле join, поэтому необходимо указать опцию -o FORMAT на join.
  5. Заголовок файла2 не удаляется.
  6. Не вызывает проблем, но ненужная обработка: tail не нужен в файле1, потому что awk может пропустить первую строку.
  7. Ненужная опция -F ' ' для awk.

Исправление этих проблем дает следующее:

#!/bin/bash
head -1 file2
join -t '   ' -2 2 -a 1 -e NoMatch -o 2.1,2.2,2.3 \
 <(awk 'NR==1{next} {print $0}' file1.txt | sort) \
 <(tail -n +2 file2 | sort -k2)

Что дает следующий вывод с разделителями табуляции:

value   ID1     ID2
1       a       aaaa1
1       a       aaaa2
1       b       bbbb1
1       b       bbbb2
1       b       bbbb3
NoMatch NoMatch NoMatch
1       d       aaaa4
3
10.09.2018, 14:10
2 ответа

Один из способов переноса такого рода вещей заключается в следующем:

sed -e '
   #... assuming prev sed cmds made pattern space carry newline(s)
   y/\n_/_\n/     ;# exchange newlines with an underscore
   s/^[^_]*_//    ;# remove up till the first underscore, ummm newline
   y/\n_/_\n/     ;# revert the transformation
' 
2
27.01.2020, 21:15

Глупо, но работает:

sed 'h;G;s/\n/&&/;s/^\(.*\)\n\(.*\)\n\1\2$/\2/'

Что это? Вы удваиваете весь контент, затем заменяете первую новую строку двумя новыми строками. Таким образом, у вас есть один и тот же контент дважды с одной дополнительной новой строкой после первой строки. Теперь с помощью обратных ссылок вы можете идентифицировать различные части.

Если вы не хотите использовать буфер удержания:

sed 's/.*/&&/;s/\n/&&/;s/^\(.*\)\n\(.*\)\1\2$/\2/'

И нет, мне это не нравится. Если есть способ избежать этого, избегайте его.

1
27.01.2020, 21:15

Теги

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