переформатирование и очистка CSV-файла с помощью фигурных скобок, совпадающих в разных строках

#regex #awk #text-processing

#регулярное выражение #awk #обработка текста

Вопрос:

Я хотел бы переформатировать чистый файл ascii, test.txt , содержащий (всего лишь выборку из 10 строк из нескольких сотен):

 {0.91, 0.87, -69.79, 
  -0.3149, 0.05}, {0.9392, 
      1.089, 69, -0.31, 
      0.052}, {-0.8768, 0.7025, 
      69.80, -0.314, 0.053}, 
     {0.930, -1.2638750861516, 69.79, 
      0.314, 0.05301}, {0.9367, 
      -1.368063705085268, 69.79962, -0.31, 
      0.052}, {0.946, -1.644, 
      69.7, 0.3, 0.052}
  

в конечный файл, test_processed.txt , содержащий (для того же образца):

 0.91, 0.87, -69.79, -0.3149, 0.05 
0.9392, 1.089, 69, -0.31, 0.052 
-0.8768, 0.7025, 69.80, -0.314, 0.053 
0.930, -1.2638750861516, 69.79, 0.314, 0.05301 
0.9367, -1.368063705085268, 69.79962, -0.31, 0.052} 
0.946, -1.644, 69.7, 0.3, 0.052
  

То есть обычный CSV-файл, каждая строка которого содержит ровно пять полей в исходных парах совпадающих фигурных скобок.

Я попытался немного поработать с gawk и regex’es, но не смог понять, как с этим справиться; У меня такое чувство, что настройка с помощью переменных RS и ORS awk могла бы помочь, но не смогла продвинуться вперед…

Ответ №1:

Используя gnu-awk , вы можете использовать этот awk using RS для сопоставления чего-либо между {...} ними, а затем удалить начальную { , конечную } и новую строки:

 awk -v RS='{[^}] }' 'RT{gsub(/^{|}$|n */, "", RT); print RT}' file
  
 0.91, 0.87, -69.79, -0.3149, 0.05
0.9392, 1.089, 69, -0.31, 0.052
-0.8768, 0.7025, 69.80, -0.314, 0.053
0.930, -1.2638750861516, 69.79, 0.314, 0.05301
0.9367, -1.368063705085268, 69.79962, -0.31, 0.052
0.946, -1.644, 69.7, 0.3, 0.052
  

Как это работает:

  • -v RS='{[^}] }' : Устанавливает соответствие разделителя записей для {...}
  • RT : Проверяет, RT не пусто ли оно. RT задается как строка из входных данных, соответствующая RS шаблону.
  • {...} является ли действие блоком в awk
  • gsub(/^{|}$|n */, "", RT) : Удаляет начало { , конец } и разрыв строки, за которыми следует 0 или более пробелов из RT
  • print RT : печатает измененные RT

Комментарии:

1. Это сработало; спасибо! Не могли бы вы немного объяснить логику команды?

2. Я добавлю больше объяснений в ответ.

Ответ №2:

Не могли бы вы, пожалуйста, попробовать следовать GNU awk , написанному и протестированному с показанными примерами.

 awk -v RS="" -v FS="[}{]" '{for(i=2;i<=NF;i =2){gsub(/n   /," ",$i);print $i}}' Input_file
  

вывод будет следующим.

 0.91, 0.87, -69.79,  -0.3149, 0.05
0.9392,  1.089, 69, -0.31,  0.052
-0.8768, 0.7025,  69.80, -0.314, 0.053
0.930, -1.2638750861516, 69.79,  0.314, 0.05301
0.9367,  -1.368063705085268, 69.79962, -0.31,  0.052
0.946, -1.644,  69.7, 0.3, 0.052
  

Ответ №3:

С GNU awk для RS и RT с несколькими символами:

 $ awk -v RS='{[^}] }' 'RT{$0=RT; gsub(/[{}]/,""); $1=$1; print}' file
0.91, 0.87, -69.79, -0.3149, 0.05
0.9392, 1.089, 69, -0.31, 0.052
-0.8768, 0.7025, 69.80, -0.314, 0.053
0.930, -1.2638750861516, 69.79, 0.314, 0.05301
0.9367, -1.368063705085268, 69.79962, -0.31, 0.052
0.946, -1.644, 69.7, 0.3, 0.052