Зайві коми в CSV
Зустрівся з ситуацією класу «перестаралися з локалізацією».
Підкинули мені як вхід до симуляції однієї системи лог-файли, про які програма, що їх згенерувала, думала, що вона робить файли CSV. Воно, може, так би й було, якби не те, що та програма подивилася на мову операційної системи і в числах замість «рухомої крапки» втулила «рухому кому». Результат — такі числа сприймаються скрізь як два незалежних поля з цілими числами.
Пошукати, чи не можна у програмі увімкнути фіксовано використання в числах розділювача-крапки, я порадив, але ж із вже отриманими мегабайтними логами реальних процесів треба щось робити…
Ці файли мають практично вільний формат (рядки мають різну кількість полів), але, на щастя, перед кожним числовим полем йде текстова назва цього поля, маємо набір пар «назва даних», «значення» (значення може бути текстовим, але у випадкові із зайвими комами це не важливо).
Тобто не зустрічаються два цілих числа підряд і якщо вже кома з двох сторін має цифри, то її гарантовано слід замінити крапкою. «Ніколи» — це ніколи там, де є числа з рухомою комою. На початку кожного рядка йде фрагмент фіксованої структури, де є і текстові рядки, і декілька цілих чисел підряд. Рядок розбивається на дві частини, першу слід залишити як була, у другій всі коми, обрамлені цифрами, замінити на крапки.
Тут теж є трішки програмістського щастя — між цим фрагментом і «хвостом» з довільними іменованими даними завжди зустрічається одна й та ж сама послідовність літер, скажімо, vli
, що дає можливість не рахувати поля на початку і не сподіватися на фіксовану довжину заголовка, а просто розділити рядок на дві частини по цій комбінації літер.
Все перераховане може зробити коротенький скрипт мовою AWK:
i = index($0, "vli")
s0 = substr($0, 1, i)
s1 = substr($0, 1+i)
print s0 gensub(/([0-9]),([0-9])/, "\\1.\\2", "g", s1)
}