2017-02-16 15 views
2

У меня есть файл CSV, с которым я работаю, чтобы управлять с помощью sed. То, что я делаю, это вставить текущий YYYY-MM-DD HH: MM: SS в пятое поле после IP-адреса. Как вы можете видеть ниже, каждое значение заключено в двойные кавычки, и каждый столбец CSV разделяется запятой.Использование SED для добавления значений после 5-го поля файла CSV, который также является IP-адресом

"12345","","","None","192.168.2.1","qqq","000" 
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","qqq","000" 

Использование команды: sed 'N;s/","/","YYYY-MM-DD HH:MM:SS","/5' FILENAME Я добавляю в дату после 5-го поля. Обычно это работает, но часто определенные значения в CSV-файле испортили этот счет, который вставляет дату в 5-е поле. Чтобы исправить эту проблему, как я могу не только добавить дату после 5-го поля, но и убедиться, что пятое поле является IP-адресом?

Конечный результат должен быть:

"12345","","","None","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000" 
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000" 

Пожалуйста, ответьте с тем, как это делается с помощью SED и AWK не. И как я могу убедиться, что пятое поле также является IP-адресом до даты добавления?

+1

Почему вы не можете использовать awk? Это было бы намного лучше. –

+0

Что должно произойти на линиях, где $ 5 не является IP-адресом? –

+1

Насколько чист ваш CSV-файл? Есть ли поля без двойных кавычек вокруг них? Существуют ли когда-либо поля с символом '... ...? ...? ', Чтобы указать двойную кавычку, встроенную в строку? Существуют ли поля с запятыми между кавычками ('' this, that '')? Это не ужасно критично, но нужно ли задавать значение «YYYY-MM-DD HH: MM: SS» из переменной (например, выход «date +»% Y-% m-% d% H:% M:% S'' захватывается и заменяется командой 'sed')? –

ответ

2

Этот ответ в настоящее время предполагается, что файл CSV прекрасно согласуется и просто (как в выборочных данных), так что:

  • Поле всегда имеет двойные кавычки вокруг них.
  • Нет таких полей, как "…""…", чтобы указать двойную кавычку, встроенную в строку.
  • Между кавычками ("this,that") нет полей с запятыми.

Учитывая эти предпосылки, этот sed скрипт делает работу:

sed 's/^\("[^"]*",\)\{4\}"\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}",/&"YYYY-MM-DD HH:MM:SS",/' 

Давайте разделим этот шаблон поиска на куски:

  • ^\("[^"]*",\)\{4\}

    Match начало строки за которым следуют: 4 повторения двойной кавычки, последовательность из нуля или более не двойных кавычек, двойная цитата и запятая.

    Другими словами, это идентифицирует первые четыре поля.

  • "\([0-9]\{1,3\}\.\)\{3\}

    матча двойные кавычки, а затем 3 повторов 1-3 десятичных цифр, за которыми следует точка - первые три тройки с IPv4 десятичном адреса.

  • [0-9]\{1,3\}",

    матч 1-3 десятичных цифры следует двойной кавычка и запятая - последний триплет из IPv4 десятичного адреса плюс конец поля.

Очевидно, что для каждой индивидуальности CSV-файлов, с которыми вам также необходимо иметь дело, вы должны изменить регулярные выражения. Это не тривиально.

Используя расширенные регулярные выражения (включены по -E как на GNU и BSD sed), вы могли бы написать:

sed -E 's/^("(([^"]*"")*[^"]*)",){4}"([0-9]{1,3}\.){3}[0-9]{1,3}",/&"YYYY-MM-DD HH:MM:SS",/' 

Узор распознавать первые 4 поля является более сложным, чем раньше. Он соответствует 4 повторениям: двойная кавычка, ноль или более вхождений {нулевых или более не двойных кавычек, за которыми следуют две двойные кавычки}, за которыми следуют ноль или более не двойных кавычек, за которыми следуют двойная кавычка и запятая.

Вы также можете написать, что в классических sed (основных регулярных выражений) с либеральной окроплением обратной косой черты:

sed 's/^\("\(\([^"]*""\)*[^"]*\)",\)\{4\}"\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}",/&"YYYY-MM-DD HH:MM:SS",/' 

Учитывая данные файла:

"12345","","","None","192.168.2.1","qqq","000" 
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","qqq","000" 
"23456","Quaternions","2.3","Pisces","Heredotus","qqq","000" 
"34567","Commas, oh commas!","3.14159","""Quotes"" quoth he","192.168.99.37","zzz","011" 
"45678","Commas, oh commas!","3.14159","""Quote me"",""or not""","192.168.99.37","zzz","011" 

Первый сценарий показан производит вывод :

"12345","","","None","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000" 
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000" 
"23456","Quaternions","2.3","Pisces","Heredotus","qqq","000" 
"34567","Commas, oh commas!","3.14159","""Quotes"" quoth he","192.168.99.37","zzz","011" 
"45678","Commas, oh commas!","3.14159","""Quote me"",""or not""","192.168.99.37","zzz","011" 

Первые две строки правильные mapp ред; третий правильно не изменился, но последние два должны были отображаться и не были.

Вторые и третьи команды производят:

"12345","","","None","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000" 
"67890","ABC-1234-5678","9.9","Low","192.168.2.1","YYYY-MM-DD HH:MM:SS","qqq","000" 
"23456","Quaternions","2.3","Pisces","Heredotus","qqq","000" 
"34567","Commas, oh commas!","3.14159","""Quotes"" quoth he","192.168.99.37","YYYY-MM-DD HH:MM:SS","zzz","011" 
"45678","Commas, oh commas!","3.14159","""Quote me"",""or not""","192.168.99.37","YYYY-MM-DD HH:MM:SS","zzz","011" 

Обратите внимание, что Heredotus не модифицированная (правильно), а последние две строк получить строку даты добавлена ​​после IP-адреса (также правильно).

Эти последние регулярные выражения не для слабонервных.

Очевидно, что если вы хотите настаивать на том, что IP-адреса соответствуют только номерам в диапазоне 0..255 в каждом компоненте, без ведущего 0, вам нужно усилить часть соответствия IP-адресов регулярному выражению. Это можно сделать; это некрасиво. Это проще всего сделать это с расширенными регулярными выражениями:

([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]) 

Вы хотите использовать этот блок в месте каждого [0-9]{3} единицы в регулярных выражениях, показанных ранее.

Обратите внимание, что это все еще не пытается обрабатывать поля, не окруженные двойными кавычками.

Он также не определяет значение для замены из команды date. Это выполнимо с (если элементарно не то) рутиной сценариев оболочки тщательно управления цитатой:

dt=$(date +'%Y-%m-%d %H:%M:%S') 
sed -E 's/^("(([^"]*"")*[^"]*)",){4}"([0-9]{1,3}\.){3}[0-9]{1,3}",/&"'"$dt"'",/' 

'…"'"$dt"'",/' последовательностью является частью того, что начинается как одинарные кавычками.Первая двойная кавычка - это простые данные в строке; следующая одинарная кавычка заканчивает цитирование, "$dt" интерполирует значение из date внутри двойных кавычек оболочки (так что пространство не вызывает никаких проблем), тогда одинарная кавычка возобновляет однокаскадную нотацию, добавляя еще одну двойную кавычку, запятую и слэш перед строкой (аргумент sed) завершается.

+0

Работал как шарм. Ты человек Джон. Мастер доверия. – Alby

1

Try:

awk -vdate1=$(date +"%Y-%m-%d") -vdate2=$(date +"%H:%M:%S") -F, '$5 ~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]/{$5=$5 FS date1 " " date2} 1' OFS=, Input_file 

Кроме того, если вы хотите редактировать один и тот же input_file вы можете взять выше результатов работы команды в временный файл, а затем переименуйте (мв команда) к тому же input_file

Добавление один- лайнерская форма решения тоже сейчас.

awk -vdate1=$(date +"%Y-%m-%d") -vdate2=$(date +"%H:%M:%S") -F, ' 
      $5 ~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]/{ 
      $5=$5 FS date1 " " date2 
               } 
      1 
    ' OFS=, Input_file 
+3

Хотя я согласен с тем, что awk будет хорошим инструментом для этого, он игнорирует запрос использовать sed, а не awk. –

 Смежные вопросы

  • Нет связанных вопросов^_^