Удалить только запятые в двойных кавычках

10

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

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решение для этого.

Авинаш Радж
источник
От 56,72,"12,34,54",x,y,"foo,a,b,bar"к 56,72,123454,x,y,"a,b", fooи barесть исчезают. Это ваш желаемый результат?
cuonglm
Пример, который вы используете, немного сбивает с толку, поскольку некоторые элементы (например, fooи bar) удаляются вместе с запятыми. Кроме того, некоторые цитаты исчезают там, где остаются другие. Не говоря уже о том, что запятые между ними aи bостаются, а также. Есть ли какая-то закономерность к этим?
HalosGhost
отредактировал извините друзья.
Авинаш Радж
Ваши правки не прояснили ваш пример. Пожалуйста, смотрите мой последний комментарий .
HalosGhost
удаляйте все запятые внутри двойных кавычек, а также кавычки, только если в кавычках есть числа.
Авинаш Радж

Ответы:

7

Это (адаптировано здесь ) должно делать то, что вам нужно, хотя 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и \2будет bar.
    • "[0-9,]*",?: соответствует 0 или более 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.

Тердон
источник
10

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

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

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

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

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
RICi
источник
@rici: Хорошо! И используйте y///вместо того, чтобы tr///спасти нас еще одного персонажа.
cuonglm
6

Для данных CSV я бы использовал язык с настоящим анализатором CSV. Например с Руби:

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"
Гленн Джекман
источник
0

Blockquote

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

Этот код Python заменяет запятые в двойных кавычках

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

если заменить на Pipe 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()
Виджай Кумар Акарапу
источник
нужно небольшое объяснение.
Дворняга
Этот код Python используется для замены вещей в двойных кавычках
Виджай Кумар Акарапу