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

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

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

1 ответ1

2

Делать

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .