Как заменить символ в интервале, разделенном двумя другими символами из файла

405
Anand

Я должен заменить все вхождения символа вертикальной черты |запятой, ,когда они появляются между [и ]символами в каждой строке файла.

Допустим, у меня есть строка ниже в файле:

wah wah| [go great|no great|so great] | wah wah | [go great|no great|so great] 

Я хочу, чтобы мой вывод был как ниже:

wah wah| [go great,no great,so great] | wah wah | [go great,no great,so great] 

Обратите внимание, что может быть несколько [... ]пар. Вертикальные полосы между первым ]и вторым [не должны быть изменены.

Как я могу добиться этого с помощью команд оболочки? Я пробовал несколько способов, как показано ниже, но ничего не получалось.

sed '/[/,/]/s/|/,/g' abcd.csv 
0

1 ответ на вопрос

2
Scott

Делать

sed ': loop; s / \ (\ [[^] [] * \) | \ ([^] [] * \] \) / \ 1, \ 2 /; t loop ' input_file

Что происходит?

  • : loopэто метка для зацикливания; Я воспользуюсь этим через минуту.
  • s/\(\[[^][]*\)|\([^][]*\]\)/\1,\2/заменяет тот, | который появляется между [и ]с запятой. Сломано:

    s/ \( \[ [^][] * \) | \( [^][] * \] \) / \1,\2 / 
    • \(\)Разграничивает группу поиска и замены. Учитывая [... ]с |между ними, это соответствует [ вверх до (но не включая) (последний) в | качестве одной группы, и все после |вверх по (включительно) в ]качестве второй группы.
    • \[соответствует буквальному [.
    • [^][]соответствует любому символу, кроме [или] . Это ломается как
      [^] []
      т.е. экземпляр
      [^ characters_to_not_match ]
    • *- ноль или более символов, кроме [или ].
    • \)- конец группы; обсуждалось выше.
    • |это литерал |(тот, который мы хотим заменить).
    • Вторая половина регулярного выражения почти такая же, как и первая половина: соответствует группе, состоящей из нуля или более символов, отличных от [или ], за которыми следует символ ].
    • Затем замените все это первой группой, запятой и второй группой. Поскольку все в соответствующей строке находится в одной из групп, за исключением |, это функционально заменяет \на ,.
  • t loop- тест / передача. Если s команда нашла совпадение и произвела замену, вернитесь к метке и попробуйте снова (потому что s команда заменяет только по одному |за раз). Если он не нашел соответствия, завершите командный сценарий и перейдите к следующей строке.