Intereting Posts
Создание резервной копии rsync / var делает систему неустойчивой Вывод процесса `find` обрабатывает определенные поля Количество символов языка X в смешанном текстовом файле? как раздел для двойной загрузки OpenSuSE Поручить выполнить блок после успешного завершения работы другого устройства Какой текстовый редактор использовал Томпсон и Ричи в написании Unix? Как скопировать и добавить префикс к именам файлов за один шаг? Измените размер конкретного windows до определенного размера и местоположения экрана из скрипта Как сделать поиск нескольких строк с использованием awk в unix? Устанавливать корневую файловую систему из initramfs вызов xrandr заставляет забыть о вторичном дисплее Дисковый раздел при двойной загрузке Ubuntu 14.04 на Windows 10 devtoolset-4 был удален из centos-release-scl? Openswan установил NAT-туннель, но я не могу выполнить ping на удаленном компьютере Как отключить SSLv3 в Apache?

Замените все вхождения \ except \ N

У меня есть файл вроде этого:

1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N 

Я хочу заменить все вхождения \ с #, за исключением \ N, так что вывод выглядит следующим образом:

 1,2,subjects,#mat#hs,unix#,#Nato,\N,123,\N 

Я пытаюсь написать команду sed, которая выглядит как:

 sed -e 's@\\([^N])@#\1/g' filename 

но это не удастся для всех значений везде, где есть \ N в начале для ex. \Nato в приведенном выше примере.

Может кто-нибудь, пожалуйста, помогите мне разобраться в команде sed (regex) для моего требования.

Я не так хорошо разбираюсь в sed . Но это можно сделать легко в perl используя регулярное выражение:

 perl -pe 's/\\(?!N\b)/#/g' your_file_here 

Это напечатает измененный файл в stdout. Чтобы сделать замену, вы можете сделать:

 perl -pi -e 's/\\(?!N\b)/#/g' your_file_here 

В основном это заменяет любую обратную косую черту, за которой не следует N\b (символ N на границе слова) с # .

редактировать

Если вы абсолютно уверены, что ваши записи разделены запятой, вы можете сделать это, чтобы охватить случай, когда \N находится в конце слова (как в SOLEM\N в приведенном примере):

 perl -pe ' s/\\/#/g; s/(\A|,)\s*#N\s*(\Z|,)/$1\\N$2/g;' your_file_here 

Он просто заменяет любую обратную косую черту меткой хэша, а затем ищет #N между двумя запятыми, между началом строки и запятой или между запятой и концом строки.

 $ echo '1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N' \ | sed -r -e 's@\\([^N]|N[^,])@#\1@g' 1,2,subjects,#mat#hs,unix#,#Nato,\N,123,\N 

Изменить для \ N как часть слова: (см. Комментарии)

 $ echo '1,2,subjects,\mat\hs,unix\,\SOLEM\N,\N,123,\N' \ | sed -r -e 's@,\\N$@,:SINGLE_N_PLACEHOLDER:@g' \ -e 's@^\\N,@:SINGLE_N_PLACEHOLDER:,@g' \ -e 's@,\\N,@,:SINGLE_N_PLACEHOLDER:,@g' \ -e 's@\\@#@g' \ -e 's@:SINGLE_N_PLACEHOLDER:@\\N@g' 1,2,subjects,#mat#hs,unix#,#SOLEM#N,\N,123,\N 

Это уродливое и ненадежное (строка-заполнитель должна быть уникальной, перестанет работать, если этот шаблон появится в тексте), но я не нашел способ сделать утверждения использования sed такими, как они поддерживают PCRE / Perl.

Вы можете сделать это короче:

 $ echo '1,2,subjects,\mat\hs,unix\,\SOLEM\N,\N,123,\N' \ | sed -r -e 's@\\@#@g' \ -e 's@(,|^)#N(,|$)@\1\\N\2@g' 1,2,subjects,#mat#hs,unix#,#SOLEM#N,\N,123,\N 

Но в этом случае один #N является заполнителем, который еще не должен появляться в строке.

 sed -e 's@\\\([^N]\|\(N[a-zA-Z]\|$\)\)@#\1@g' your_file_here 

Объяснение: Заменить все \ последующим

  • ничего, кроме N ,
  • или N за которым следует любая буква в [a-zA-Z] (при необходимости продлите это)
  • конец линии

с # и оставшейся совпадением.

 $ echo '1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N' | sed -r -e 's/\\N/XELI/g' | sed -e 's/\\/#/g' | sed -e 's/XELI/\\N/g' 1,2,subjects,#mat#hs,unix#,\Nato,\N,123,\N 

Я с большей готовностью разглядываю его:

  • замените \ N на какой-то несуществующий символ,
  • затем замените / на #
  • и замените / N назад