В Cygwin (или Windows 7) сопоставьте слово, посмотрите назад, пропустите слово и напечатайте x количество слов, разделенных запятыми

У вас болит голова, пытаясь понять волнистые awks и greps, но далеко не продвинулись. У меня есть 100 тысяч файлов, из которых я пытаюсь извлечь одну строку. Примерный набор строк файла:

Revenue,876.08,,9361.000,444.000,333.000,222.000,111.00,485.000,"\t\t",178.90,9008.98
EV to Revenue,6.170,0.65,3.600,2.60,1.520,1.7,"\t\t",190.9,9008.98,80.9,87

(между двойными кавычками есть две вкладки. Здесь я представляю их с помощью \t. Это настоящие вкладки с пробелами)

Я пытаюсь вывести только эту строку, начинающуюся с Revenue:

Revenue,444.000,333.000,222.000,111.000

Эта выходная строка выводит первое слово строки и запятую (т. е.: Доход). Затем она находит две вкладки, заключенные в двойные кавычки, просматривает назад, пропуская первый набор чисел, разделенных запятыми (также предположим, что вместо чисел могут быть ничего, то есть: просто пробел, разделенный запятой), а затем выводит 4 набора чисел, разделенных запятыми.

Выполнимо ли это с помощью простой команды grep или awk, cut или tr на cygwin, которая не будет медведем для запуска на 100K файлов? Чтобы уточнить, есть 100K файлов, которые выглядят очень похоже. Каждый файл будет содержать много строк (разделенных новой строкой/возвратом каретки). Некоторые строки будут содержать слово «Доход» в начале, некоторые в середине (как во второй строке примера, которую я вставил выше) и т. д. Меня интересуют только те строки, которые начинаются с «Доход», за которым следует запятая, а затем последовательность выше . Каждый файл будет содержать эту конкретную строку.

В качестве завершения такого рода задач (поскольку это также потребуется для работы с файлами размером 100 КБ), что нужно добавить в sed, чтобы также распечатать текущее имя файла, с которым выполняется операция? то есть: вывод следующим образом:

FileName1: Revenue, 444 000 333 000 222 000 111 000 [я опубликую ответ здесь, если найду его]

Благодарю вас!

Спасибо Sputnick за редактирование моего вопроса, чтобы он выглядел аккуратно, и спасибо shellter за ответ. Эд, твое решение выглядит очень хорошо. Я тестирую его и отвечу с информацией плюс мое понимание того, как работает это регулярное выражение. Большое спасибо, что нашли время написать это!


person lexa    schedule 23.12.2014    source источник


Ответы (1)


Поскольку это всего лишь простая замена одной строки, она больше всего подходит для sed:

$ sed -n -r 's/(^Revenue)(,[^,]*){3}(.*),[^,]*,"\t\t".*/\1\3/p' file
Revenue,444.000,333.000,222.000,111.00

но вы можете сделать то же самое в awk с помощью gensub() (gawk) или match()/substr() или подобных. Он будет работать в мгновение ока, независимо от того, какой инструмент вы используете.

person Ed Morton    schedule 23.12.2014
comment
Спасибо, Эд. Это работает очень хорошо! Если у вас будет время, не могли бы вы сделать заметку о том, правильно ли я понимаю? (^Revenue) соответствует всем строкам, начинающимся с Revenue. Также сохраните это в памяти, чтобы получить позже как \1. (,[^,]*){3} Соответствует запятой, а затем любому количеству запятых, обозначенному знаком *. Потом я как-то потерялся. :) - person lexa; 23.12.2014
comment
это запятая, затем любое количество незапятых (например, ,abc), и вся эта часть повторяется 3 раза. например ,abc,,defgh. - person Ed Morton; 23.12.2014
comment
А вот версия команды Эда для печати имени файла, которая работает в моей оболочке bash cygwin: for file in .csv; сделать printf %s $file ; sed -n -r 's/(^Доход)(,[^,]){9}(.*),[^,]*,\t\t.*/\1\3/p '${файл}; Выполнено - person lexa; 24.12.2014