Фильтрация данных в файле CSV

#regex #linux #csv #awk #sed

#регулярное выражение #linux #csv #awk #sed

Вопрос:

У меня есть файл CSV в этом формате

 a,b,c,d,e,f,no disk detected
a,b,c,d,e,f,disk run into error
a,b,c,d,e,f,no memory in the server
a,b,c,d,e,f,memory has correctable errors
  

в последнем столбце мне нужно выполнить поиск по слову

диск и замените его ошибкой диска, память и замените ее ошибкой памяти, с которой я уже разобрался

  cat filename.csv |awk -F "," '{print $NF}' |sed 's/^.*disk.*$/disk error/'  |sed 's/^.*memory.*$/memory error/' 
  

Теперь часть, в которой мне нужна помощь, когда sed заменит эту строку, можно ли записать в тот же файл (filename.csv) или сгенерировать новый файл со всеми столбцами обновленный столбец, чтобы новый файл выглядел следующим образом

  a,b,c,d,e,f,disk error
 a,b,c,d,e,f,disk error
 a,b,c,d,e,f,memory error
 a,b,c,d,e,f,memory error
  

Ответ №1:

Это проще сделать с sed :

 sed -E 's/^(. ,).*(disk|memory).*$/12 error/' file.csv
  

 a,b,c,d,e,f,disk error
a,b,c,d,e,f,disk error
a,b,c,d,e,f,memory error
a,b,c,d,e,f,memory error
  

Чтобы внести изменения встроенно в тот же файл, используйте:

 sed -i.bak -E 's/^(. ,).*(disk|memory).*$/12 error/' file.csv
  

== Подробности ==

Регулярное выражение для поиска:

  • ^ : Начать
  • (. ,) : Жадное сопоставление до последней запятой и запись его в группу # 1
  • .*(disk|memory) : Сопоставьте 0 или более символов перед сопоставлением disk или memory и запишите его в группу # 2
  • .*$ : Сопоставьте 0 или более символов до конца

Шаблон замены:

  • 1 : Обратная ссылка на группу # 1 для размещения текста до последней запятой обратно
  • 2 error : Добавить disk error или memory error

Ответ №2:

awk Решение:

 awk -F, '{if ($NF~/disk/) $NF="disk error"; if ($NF~/memory/) $NF="memory error";}1' OFS=, file
  

С GNU awk версии 4.1.0 вы можете добавить -i inplace переключатель для изменения file места ввода.
В противном случае попробуйте awk .... file | tee file .

Итак, приведенная выше команда сама по себе не требует GNU awk, но если у вас есть GNU awk, вы можете сделать это более кратким способом:

 awk -F, '{match($NF,"(disk|memory)",m);$NF=m[1] " error";}1' OFS=, file
  

NF означает номер столбца, $NF означает последний столбец.
-F, установите для FS разделителя полей значение запятой.
OFS=, установите разделитель полей вывода на запятую.

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

1. Мы можем обойтись без самой последней точки с запятой.

2. @ClaesWikner Да, это можно сохранить. Спасибо, что упомянули об этом. Я добавил это сюда, чтобы иметь какое-то завершение , просто чувствую себя лучше 🙂