Ограничение замены для совпадения пробелов Использование sed? - PullRequest
1 голос
/ 06 марта 2011

Есть ли способ замены только в пределах области совпадения с использованием sed?

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

Ввод:

'ECJ-4YF1H10.6Z' ! 'CAP' ! '10.0uF' ! 'TOL' ; MGCDC1008.S1 MGCDC1009.A2

Желаемый результат:

'ECJ-4YF1H10-6Z' ! 'CAP' ! '10_0uF' ! 'TOL' ; MGCDC1008.S1 MGCDC1009.A2

Или это просто работа, к которой могут относиться perl или awkбыть лучше подходит?

Спасибо за помощь,

Марк

Ответы [ 3 ]

0 голосов
/ 07 марта 2011

Дайте следующую попытку, использующую технику «разделяй и властвуй»:

sed "s/\('[^']*'\)/\n&\n/g;s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g;s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g;s/\n//g" inputfile

Пояснение:

  • s/\('[^']*'\)/\n&\n/g - Добавить новые строки до и после каждой пары одинарных кавычек с их содержанием
  • s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g - Используя новую строку и одинарные кавычки для ввода, замените точку чертой для строк, оканчивающихся на «Z»
  • s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g - Используя новую строку и одинарные кавычки для ввода, замените точку штрихом для строк, заканчивающихся на «uF»
  • s/\n//g - Удалить новые строки, добавленные на первом шаге

Вы можете ограничить действие команды только определенными строками:

sed "/foo/{s/\('[^']*'\)/\n&\n/g;s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g;s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g;s/\n//g}" inputfile

где вместо "foo" вы подставили бы некоторое регулярное выражение.

Некоторые версии sed предпочитают кормить ложкой (вместо точек с запятой между командами используйте -e):

sed -e "/foo/{s/\('[^']*'\)/\n&\n/g" -e "s/\(\n'[^.]*\)\.\([^']*Z'\)/\1-\2/g" -e "s/\(\n'[^.]*\)\.\([^']*uF'\)/\1_\2/g" -e "s/\n//g}" inputfile
0 голосов
/ 07 марта 2011

это работа, наиболее подходящая для awk или любого языка, который поддерживает разрыв / разбиение строк. IMO, использующий sed для этой задачи, который основан на регулярных выражениях, хотя и выполним, труден для чтения и отладки, поэтому не является наиболее подходящим инструментом для работы. Не в обиду седаным фанатикам.

awk '{
  for(i=1;i<=NF;i++)  {
     if ($i ~ /\047/ ){
        gsub(".","_",$i)
     }
  } 
}1' file

Выше указано, что для каждого поля (по умолчанию разделителем полей является пробел), проверьте, есть ли одинарная кавычка, и, если она есть, подставьте "." на "_". Этот метод прост и не требует сложного регулярного выражения.

0 голосов
/ 06 марта 2011
$ cat phoo1234567_sedFix.sed
#! /bin/sed -f
/'[0-9][0-9]\.[0-9][a-zA-Z][a-zA-Z]'/s/'\([0-9][0-9]\)\.\([0-9][a-zA-Z][a-zA-Z]\)'/\1_\2/

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

Обратите внимание, что cmd состоит из 2 частей, "/'[0-9][0-9].[0-9][a-zA-Z][a-zA-Z]'/" говорит: должен соответствовать линиям с этим шаблоном, в то время как завершающий "s / '([0-9] [0-9]). ([0-9] [a-zA-Z] [a-zA-Z])' / \ 1_ \ 2 / ", это часть, которая выполняет замену. Вы можете добавить 'g' после последнего '/', чтобы эта замена произошла во всех экземплярах этого шаблона в каждой строке.

Пары \ (\) в шаблоне сопоставления преобразуются в пронумерованные буферы на стороне замещения команды (т. Е. \ 1 \ 2). Это то, что дает силу sed, которой нет в awk.

Если вы собираетесь выполнять большую часть подобного рода работы, я настоятельно рекомендую книгу О'Рилли «Седь и пробуждайся». Время, потраченное на то, как работает sed, будет возвращено много раз.

Надеюсь, это поможет.

P.S. поскольку вы выглядите как новый пользователь, если вы получите ответ, который поможет вам, не забудьте пометить его как принятый или поставить + (или -) в качестве полезного ответа.

...