Удалите только запятые, присутствующие в двойных кавычках

В текстовом файле я хочу удалить (запятые), а также " (кавычки)» (только если двойные кавычки содержат числа, разделенные запятыми).

 56,72,"12,34,54",x,y,"foo,a,b,bar" 

Ожидаемый выход

 56,72,123454,x,y,"foo,a,b,bar" 

Примечание. Я показываю приведенную выше строку как пример. Мой текстовый файл содержит много строк, как указано выше, и числа, разделенные запятыми, присутствующими в двойных кавычках, должны отличаться. То есть,

 56,72,"12,34,54",x,y,"foo,a,b,bar" 56,92,"12,34",x,y,"foo,a,b,bar" 56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar" 56,72,x,y,"foo,a,b,bar","12,34,54" 56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo" 

Ожидаемый результат:

 56,72,123454,x,y,"foo,a,b,bar" 56,92,1234,x,y,"foo,a,b,bar" 56,72,12345478765467,x,y,"foo,a,b,bar" 56,72,x,y,"foo,a,b,bar",123454 56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo" 

Там n число чисел, присутствующих в двойных кавычках, разделенных запятыми. А также оставить двойные кавычки, которые содержат символы как есть.

Я люблю инструмент обработки текстов sed . Я рад, если вы sed какое-либо решение sed для этого.

4 Solutions collect form web for “Удалите только запятые, присутствующие в двойных кавычках”

Это (адаптировано отсюда ) должно делать то, что вам нужно, хотя Perl-интерфейс @ rici намного проще:

 $ sed -r ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;ta; s/""/","/g; s/"([0-9]*)",?/\1,/g ' file 56,72,123454,x,y,"foo,a,b,bar" 56,92,1234,x,y,"foo,a,b,bar" 56,72,12345478765467,x,y,"foo,a,b,bar" 56,72,x,y,"foo,a,b,bar",123454, 56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo" 

объяснение

  • :a : определить метку, называемую a .
  • s/(("[0-9,]*",?)*"[0-9,]*),/\1/ : Это нужно разбить
    • Прежде всего, используя эту конструкцию: (foo(bar)) , \1 будет foobar а \2bar .
    • "[0-9,]*",? : соответствует 0 или более 0-9 или 0-9 затем 0 или 1,.
    • ("[0-9,]*",?)* : Соответствует 0 или более из приведенного выше.
    • "[0-9,]* : соответствует 0 или более 0-9 или , которые появляются сразу после "
  • ta; : вернитесь к метке a и запустите снова, если замена была успешной.
  • s/""/","/g; : Постобработка. Замените "" на "," .
  • s/"([0-9]*)",?/\1,/g : удалить все кавычки вокруг чисел.

Это может быть проще понять с помощью другого примера:

 $ echo '"1,2,3,4"' | sed -nr ':a;s/(("[0-9,]*",?)*"[0-9,]*),/\1/;p;ta;' "1,2,34" "1,234" "1234" "1234" 

Таким образом, пока вы можете найти число, которое находится прямо после цитаты, а затем запятая и другое число, соедините два числа вместе и повторите процесс, пока это станет невозможным.

На этом этапе я считаю полезным упомянуть цитату из info sed которая появляется в разделе, описывающем расширенные функции, такие как метка, используемая выше (спасибо за поиск, если @Braiam):

В большинстве случаев использование этих команд указывает на то, что вы, вероятно, лучше программируете в чем-то вроде awk или Perl.

Если perl в порядке, вот короткий (и, вероятно, быстрый, если не обязательно простой :)) способ сделать это:

 perl -pe 's:"(\d[\d,]+)":$1=~y/,//dr:eg' file 

Флаг e для оператора s::: (который является еще одним способом записи s/// ) заставляет замену обрабатывать как выражение, которое оценивается каждый раз. Это выражение берет захват $1 из регулярного выражения (которое уже пропускает кавычки) и переводит ( y/// , который также можно записать как tr/// ), удалив ( /d ) все запятые. Флаг r в y необходим для того, чтобы получить значение как переведенную строку, а не количество переводов.

Для тех, кто каким-то образом одурачивает perl, вот эквивалент python. Python на самом деле не инструмент оболочки с одним слоем, но иногда его можно объединить в сотрудничестве. Следующие строки могут быть записаны как одна строка (в отличие от циклов, которые не могут быть), но горизонтальная прокрутка делает ее (даже больше) нечитаемой:

 python -c ' import re; import sys; r=re.compile("\"(\d+(,\d+)*)\""); all(not sys.stdout.write(r.sub(lambda m:m.group(1).replace(",",""),l)) for l in sys.stdin) ' < file 

Для CSV-данных я бы использовал язык с реальным синтаксическим анализатором CSV. Например, с Ruby:

 ruby -rcsv -pe ' row = CSV::parse_line($_).map {|e| e.delete!(",") if e =~ /^[\d,]+$/; e} $_ = CSV::generate_line(row) ' <<END 56,72,"12,34,54",x,y,"foo,a,b,bar" 56,92,"12,34",x,y,"foo,a,b,bar" 56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar" 56,72,x,y,"foo,a,b,bar","12,34,54" 56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo" END 
 56,72,123454,x,y,"foo,a,b,bar" 56,92,1234,x,y,"foo,a,b,bar" 56,72,12345478765467,x,y,"foo,a,b,bar" 56,72,x,y,"foo,a,b,bar",123454 56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo" 

Blockquote

Привет. Вот код Python для замены запятых в двойных кавычках, запятые заменяются символом pipe (|)

Этот код Python должен заменить запятые, заключенные в двойные кавычки

например: x, y, z, 1,2, "r, e, t, y", h, 8,5,6

если заменить трубкой x, y, z, 1,2, "r | e | t | y", h, 8,5,6

если заменить на нуль x, y, z, 1,2, "rety", h, 8,5,6

 writingFile = open('FileToWrite', 'w') with open('FileToRead') as f: while True: c = f.read(1) if not c: print ("End of file") break print ("Read a character:", c) if c=='"': writingFile.write(c) c = f.read(1) while c != '"': if c== ',': c= '|' writingFile.write(c) c = f.read(1) writingFile.write(c) writingFile.close() 
  • Как отобразить имя дистрибутива (только) из lsb_release -i
  • Найти и заменить с помощью командной строки
  • как удалить двойные кавычки в csv
  • Удалить строки, которые соответствуют точно и только строке
  • Заменить шаблон в файле с шаблоном во втором файле
  • Как изменить специальный символ в linux с помощью переменной
  • globbing, sed или awk html-файлы
  • Shell Script для удаления двойных кавычек в пределах значения столбца
  • Как сохранить сложное регулярное выражение для многократного повторного использования в sed?
  • Как использовать sed для печати части строки, содержащей хеши (или любое альтернативное решение)?
  • regex find заменяет строки, начинающиеся или начинающиеся с обратной косой черты
  • Interesting Posts
    Linux и Unix - лучшая ОС в мире.