У меня есть CSV-файл, подобный следующему:
hostname1 | role1 | environment | tag,list | |
hostname2 | role2 | environment | tag,list,longer | |
hostname3 | role3 | environment | | |
Мне нужно выражение sed
, которое добавляет к столбцу с тегами (4 th sup> столбец) новый тег, если тегов уже нет, и вставляет новый тег с запятой, если существуют теги. Я пробовал это:
sed "s/\(^$server |.*|.*|\) \(.*|.*|$\)/\1 new,\2/" testfile.csv
, где сервер определяется внешне, например, так:
server="hostname2"
, но он не работает, и не работает с запятой, если тег список пуст.
Как бы вы сделали это с помощью sed?
Распространенная ошибка при обнаружении регулярных выражений заключается в том, что они могут использоваться в качестве синтаксического анализатора (и поэтому вы видите такие вопросы, как «как я могу проанализировать XML-файл с помощью REGEX?»). Однако вы не можете вставить слишком много логики в регулярное выражение: для сложных задач, таких как ваша, вам нужен анализатор или несколько регулярных выражений.
Если вы хотите пойти по пути регулярных выражений, вам нужно два: один для случая непустых тегов и один для поля пустых тегов. Два регулярных выражения могут выглядеть следующим образом:
s/^(hostname123 \|.*?\|.*?\|\s*)(\S+\s*\|.*?\|)$/\1new,\2/
s/^(hostname123 ?\|.*?\|.*?\|)\s*(\|.*?\|)$/\1 new \2/
Эти два выражения могут быть использованы либо с двумя sed
по конвейеру:
sed 'expression1' | sed 'expression2'
или, что лучше, с одной командой следующим образом:
sed -r -e '/^'"$server"' \|/ { s/^(.*?\|.*?\|.*?\|\s*)(\S+\s*\|.*?\|)$/\1new,\2/; s/^(.*?\|.*?\|.*?\|)\s*(\|.*?\|)$/\1 new \2/ }' testfile.csv
Это более эффективно, чем использование двух sed
с, поскольку он не анализирует файл дважды.