#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
шаблону.{...}
является ли действие блоком в awkgsub(/^{|}$|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