Как заменить запятые в скобках

У меня есть текстовый файл, который выглядит следующим образом:

12.com,128.15.8.6,TEXT1,no1,['128.15.8.6'] 23com,122.14.10.7,TEXT2,no2,['122.14.10.7'] 45.com,91.33.10.4,TEXT3,no3,['91.33.10.4'] 67.com,88.22.88.8,TEXT4,no4,['88.22.88.8', '5.112.1.10'] 

Поскольку я хочу вставить содержимое файла в таблицу с помощью команды MySQL, говорящей separated by ',', строка lat в скобках (которая может содержать строки, разделенные запятой) вызывает проблемы, когда MySQL хочет разделить их, а таблица hte не делает есть достаточно столбцов для них.

Я хочу заменить запятые между скобками [] точкой с запятой ; ,

Как я могу сделать это в Linux простым способом?

РЕДАКТИРОВАТЬ # 1

Количество строк, разделенных внутри квадратных скобок, не определяется. Это может быть 1, 2, 3 и т. Д. Мне нужно заменить , если они найдены в скобках ; ,

sed может работать так же:

 sed 'h; s/.*[[]/[/; s/,/;/g; x; s/[[].*//; G; s/\n// ' file 

Объяснение:

 sed ' h; save the entire line to hold space s/.*[[]/[/ remove anything till the opening `[` s/,/;/g replace ALL commas with semicolons x save modified bracketed text, get back original line s/[[].*// get rid of the bracketed text G append the modified text s/\n// remove the  char introduced by `G` ' file 

Поскольку строки в скобках всегда начинаются с одной кавычки, вы можете просто заменить пару следующим образом:

 $ sed "s/',/';/g" file 12.com,128.15.8.6,TEXT1,no1,['128.15.8.6'] 23com,122.14.10.7,TEXT2,no2,['122.14.10.7'] 45.com,91.33.10.4,TEXT3,no3,['91.33.10.4'] 67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'] 67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4'] 67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4'; '2.3.4.5'] 

Альтернатива, которая имеет дело с 3 или меньше

Для подстрок в скобках длиной до 3 ( ['xxx', 'yyy', 'zzz'] ). Вы можете использовать sed чтобы сделать это:

 $ sed 's/\([^\[]*\)\([^,]*\),\([^,]*\)/\1\2;\3/g' file 12.com,128.15.8.6,TEXT1,no1;['128.15.8.6'] 23com,122.14.10.7,TEXT2,no2;['122.14.10.7'] 45.com,91.33.10.4,TEXT3,no3;['91.33.10.4'] 67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'] 67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4'] 

Как это устроено

В этом решении простой поиск и замена s/.../.../g

  • s/\([^\[]*\) – сопоставляет все до [ (ноль или более) и сохраняет его в \1
  • \([^,]*\) – сопоставляет все до и сохраняет его в \2
  • , – соответствует запятой
  • \([^,]*\) – сопоставляет все, что не является запятой, и сохраняет ее в \3
  • /\1\2;\3/g – восстанавливает биты так, что теперь они \1\2;\3 , делает это жадно

Если это последнее поле и число столбцов фиксировано, вы можете использовать bash:

 while IFS=, read v1 v2 v3 v4 rest; do echo "$v1,$v2,$v3,$v4,${rest//,/;}" done 

Результат:

 12.com,128.15.8.6,TEXT1,no1,['128.15.8.6'] 23com,122.14.10.7,TEXT2,no2,['122.14.10.7'] 45.com,91.33.10.4,TEXT3,no3,['91.33.10.4'] 67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'] 

Вы можете поместить вышеупомянутые операторы в файл (вместе с #!/bin/bash вверху) и передать свой файл как stdin этому сценарию, или вы можете назвать файл в сценарии:

 while IFS=, read v1 v2 v3 v4 rest; do echo "$v1,$v2,$v3,$v4,${rest//,/;}" done < yourfile 

Это использует IFS чтобы разделить строку в. первые четыре поля присваиваются v1..v4, а все, что после этого присваивается последней переменной, здесь называемой rest . Затем echo выводит переменные, разделенные символом , а в последней переменной он заменяется на ; ,

Предполагая, что нет вложенных [...] :

 sed -e :1 -e 's/\(\[[^]]*\),/\1;/g' -e t1 < file.in > file.out 

awk довольно хорош здесь: используйте открытую скобку в качестве разделителя полей и замените все запятые во 2-м поле.

 awk 'BEGIN {FS = OFS = "["} {gsub(/,/, ";", $2)} 1' file