2012-03-24 3 views
1

Как заменить запятую после четырех и пяти с | но не те, которые следуют за одним и двумя?Регулярное выражение - Sed

\"One,Two, Three\" Four, Five, Six 

sed s'/,/|/'g 

Я был бы признателен за ответ, который может быть применен к любой запятой в уцелевших кавычках, а не только этот пример.

Другой пример:

Mr ,Joe,Lish,,\"Acme, Inc.\",\"9599 Park Avenue, Suite 301\",Manhattan,NY,10022,\"\"\"6 A MAILING LIST MMBR GENERAL\"\"\" 
+2

В целом такого рода вещи не работа для регулярных выражений, потому что язык вы просите их понять, что это не является регулярным *. – dmckee

+0

Исправить. В обычных выражениях вообще нет * состояния *, связанного с ним, что и требуется здесь. Парсеру необходимо сохранить информацию о состоянии внутри кавычек или нет. –

ответ

0

Есть предпросмотр и операторы для просмотра назад регулярных выражений. Например, вызов Javascript

bodyText = bodyText.replace (/ Aa (? = A)/g, 'AaB');

заменит текст «Aa» на «AaB», если за ним последует другое «A», оставив вас с «AaBA». Он не будет соответствовать «AaB», потому что за «Aa» не следует другое «A». Это обратный вызов.

Я считаю, что синтаксис для lookbehind? < =.

Так что если эти операторы поддерживаются пакетом, который вы используете, вы можете использовать их в соответствии с «,», предшествующим «Четырем» или «Пять», и заменять только «,».

+0

Не в любом sed, который * I * используется. – dmckee

+0

@dmckee Если вы 'alias sed =" perl -p "', то он будет работать нормально. :) – tchrist

+0

@tchrist: Ты больной, больной человек. Но умный. И я имею в виду это хорошо. – dmckee

0

Я придумал это:

echo '\"One,Two, Three\" Four, Five, Six' | sed 's/\(\("[^"]*"\)\?[^",]\+\),/\1 |/g' 

который принимает строку, как

[ ["someting"] word, ]* ["someting"] word 
+0

Это не работает для меня. Я нахожусь на Mac, используя Terminal, если это что-то меняет. – adayzdone

1

Один из способов использования sed:

Содержание script.sed:

## Substitute '\"' with '\n'. 
s/\\\"/\n/g 

## If there is an odd number of '\"' or the string doesn't end with '\"' I 
## will append some at the end. There is no danger, but it will be used to 
## avoid an infinite loop. 
## 1.- Save content to 'hold space'. 
## 2.- Remove all characters except '\n'. 
## 3.- Remove one of them because next command will add another one. 
## 4.- Put content in 'pattern space' to begin working with it. 
## So, if in original string there were 3 '\"', now there will be 6. ¡Fine! 
h 
s/[^\n]//g 
s/\n// 
H 
g 

## Label 'a'. 
:a 

## Save content to 'hold space'. 
h 

## Remove from first '\n' until end of line. 
s/\(\n\).*$/\1/ 

## Substitute all commas with pipes. 
s/,/|/g 

## Delete first newline. 
s/\n// 

## Append content to print as final output to 'hold space'. 
H 

## Recover rest of line from 'hold space'. 
g 

## Remove content modified just before. 
s/[^\n]*// 

## Save content to 'hold space'. 
h 

## Get first content between '\n'. 
s/\(\n[^\n]*\n\).*$/\1/ 
s/\n\{2,\}// 

## Susbtitute '\n' with original '\"'. 
s/\n/\\"/g 

## Append content to print as final output to 'hold space'. 
H 

## Recover rest of line from 'hold space'. 
g 

## Remove content printed just before. 
s/\n[^\n]*\n// 

/^\n/ { 
    s/\n//g 
    p 
    b 
} 

ba 

Содержание infile:

\"One,Two, Three\" Four, Five, Six 
One \"Two\", Three, Four, Five 
One \"Two, Three, Four, Five\" 
One \"Two\" Three, Four \"Five, Six\" 

Выполнить это нравится:

sed -nf script.sed infile 

следующий результат:

\"One,Two, Three\" Four| Five| Six 
One \"Two\"| Three| Four| Five 
One \"Two, Three, Four, Five\" 
One \"Two\" Three| Four \"Five, Six\" 
+0

Ответ: undefined label 'a' – adayzdone

+0

@adayzdone: Извините, я не могу воспроизвести вашу проблему. Моя версия ** GNU sed versión 4.2.1 **, что твой? – Birei

+0

Версия, которая поставляется с Mac 10.6.8 – adayzdone

1

Это может работать для вас:

sed 's/^/\n/;:a;s/\n\("[^"]*"\|[^,]\)/\1\n/;ta;s/\n,/|\n/;ta;s/.$//' file 

Expla нация:

  • Подготовить новую строку к пространству рисунка. s/^/\n/
  • Сделать этикетку :a
  • Переход на новую строку над каждой строкой между кавычки или символ, который не является запятая. s/\n\("[^"]*"\|[^,]\)/\1\n/
  • Если замена была меткой успеха для метки. ta
  • Заменить \n, на |\n.s/\n,/|\n/
  • Если замена была петлей успеха для маркировки. ta
  • Если никаких замещений не происходит, все делается так, чтобы удалить новую строку. s/.$//

EDIT:

На самом деле любой уникальный символ или комбинация символов может быть использован вместо \n:

echo 'Mr ,Joe,Lish,,\"Acme, Inc.\",\"9599 Park Avenue, Suite 301\",Manhattan,NY,10022,\"\"\"6 A MAILING LIST MMBR GENERAL\"\"\"' | 
sed 's/^/@@@/;:a;s/@@@\("[^"]*"\|[^,]\)/\[email protected]@@/;ta;s/@@@,/|@@@/;ta;s/@@@$//' 
Mr |Joe|Lish||\"Acme, Inc.\"|\"9599 Park Avenue, Suite 301\"|Manhattan|NY|10022|\"\"\"6 A MAILING LIST MMBR GENERAL\"\"\" 
+0

Что я делаю неправильно? http://i.imgur.com/NdNZ3.png – adayzdone

+0

Похоже, что ваша версия sed не разрешает символы новой строки в форме '\ n'. Попробуйте заменить все '\ n' на' ''$' \ n '"' ', если вы используете bash в качестве оболочки или вставляете реальные строки, набрав CTRL-v return. Также см. [Здесь] (http://sed.sourceforge.net/sedfaq4.html#s4.1) – potong

+0

См. Альтернативный EDIT: – potong

Смежные вопросы