Как объединить строки, начинающиеся с одинаковых элементов в текстовом файле

У меня есть текстовый файл, содержащий несколько тысяч строк следующим образом:

Файл:

abc: bla1 bla1 bla1... 
cde: bla bla bla... 
ghk: bla1 bla1 bla1... 
lmn: bla bla bla...
abc: bla2 bla2 bla2... 
bcd: bla bla bla... 
ghk: bla2 bla2 bla2... 
xyz: bla bla bla...

Я хочу объединить все строки, которые начинаются с одинаковых элементов (как 1 and 5, 3 and 7) так что у меня есть новый текстовый файл, как это:

Новый файл:

abc: bla1 bla1 bla1... * abc: bla2 bla2 bla2... 
cde: bla bla bla... 
ghk: bla1 bla1 bla1... * ghk: bla2 bla2 bla2...
lmn: bla bla bla...
bcd: bla bla bla...   
xyz: bla bla bla...

Интересно, возможно ли это решить с помощью regex и / или grepи если да, то как я могу это решить?

Я хорошо знаком с grep потому что я на TextWrangler, но также хорошо с другими текстовыми редакторами.

Помощь высоко ценится.

3 ответа

Решение

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

abc: ...
abc: ...

рядом друг с другом. Затем вы выполните это регулярное выражение через несколько проходов:

Search:
  ^(\w+): (.*)\n\1: 
Replace:
  \1: \2 

Result:
   abc: bla1 bla1 bla1... bla2 bla2 bla2...
   bcd: bla bla bla...
   cde: bla bla bla...
   ghk: bla1 bla1 bla1... bla2 bla2 bla2...
   lmn: bla bla bla...
   xyz: bla bla bla...

Если порядок имеет значение, то это регулярное выражение можно выполнить несколько раз:

Search:
  ^(\w+): (.*)\n((?:(?!\1).*\n)+)\1: (.*\n)
Replace:
  \1: \2 \4\3

Result (1st pass):
  abc: bla1 bla1 bla1... bla2 bla2 bla2...
  cde: bla bla bla...
  ghk: bla1 bla1 bla1...
  lmn: bla bla bla...
  bcd: bla bla bla...
  ghk: bla2 bla2 bla2...
  xyz: bla bla bla...

Result (2nd pass):
  abc: bla1 bla1 bla1... bla2 bla2 bla2...
  cde: bla bla bla...
  ghk: bla1 bla1 bla1... bla2 bla2 bla2...
  lmn: bla bla bla...
  bcd: bla bla bla...
  xyz: bla bla bla...

С GNU Bash. Если порядок не имеет значения.

declare -A A      # declare associative array A
# fill array
while read I L; do 
  [ ${#A[$I]} -gt 0 ] && A[$I]+=" * $L"
  [ ${#A[$I]} -eq 0 ] && A[$I]+=" $L"
done < filename
# print array
for J in "${!A[@]}"; do echo "$J${A[$J]}"; done

Выход:

xyz: bla bla bla...
lmn: bla bla bla...
abc: bla1 bla1 bla1... * bla2 bla2 bla2...
ghk: bla1 bla1 bla1... * bla2 bla2 bla2...
bcd: bla bla bla...
cde: bla bla bla...

Если вы можете использовать awk, это должно работать:

awk '{a[$1]=a[$1]?a[$1]"* "$0:$0} END {for (i in a) print a[i]}' file
ghk: bla1 bla1 bla1... * ghk: bla2 bla2 bla2...
lmn: bla bla bla...
cde: bla bla bla...
xyz: bla bla bla...
bcd: bla bla bla...
abc: bla1 bla1 bla1... * abc: bla2 bla2 bla2..

,

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