2010-12-14 2 views
6

행의 특정 부분에서만 sed를 작동 시키려면 어떻게해야합니까? 그리고 반대로, 선의 특정 부분에서 sed가 작동하지 않게하려면 어떻게해야합니까?행 부분에서만 작동하는 방법

예 :

"A a A a (A a) A (a A) a" 

내가 예를 들어, 얻을 T으로 () 사이에만을 모든 A의 대체 어떻게 :

"A a A a (T a) A (a T) a" 

그리고 주어진 다음 예제 입력 :

"F f F f (F f) F (f F) f" 
내가 예를 들어, 얻을 에 X의하지만 () 사이 하지으로 모든 F의 대체 어떻게

:

"X F X F (F의 F) X를 (F F) f "

Google을 검색했지만 사용할 수있는 것이 없습니다. 나는 sed에 관한 일반적인 질문이라고 생각합니다. 문제는 일반적인 sed "템플릿"으로 축소 될 수 있습니다.

  1. 를 보유하고 만
  2. 갖는 그들 사이보다 다른 곳에서도 작동하는 (특정 행의 모든 ​​항목에) 그들 사이에 작동하는 ...
  3. 특별한 경우 경우 FROM과에 있습니다 동일한 (사이 "및"또는 "foo"와 "Foo"등) 모두 1, 2

그것은 어떤 동작뿐만 아니라 교체 작업뿐만 아니라, 원한다면, 인쇄 등으로한다 용 문자열의 "FOO"와 "BAR"사이의 모든 것을 인쇄합니다.

"1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q" 

결과는

" d e f i j k " 

그래서, 그것을 수행하는 방법에 대한 일반적인 예는 높게 평가 될 것입니다 될 것입니다. 이 질문은 꽤 흔한 것 같지만, 아직 구글에서는 좋은 하우투가 발견되지 않았다. 나는 또한이 이 대답하기에 꽤 어려울 것이라고 생각합니다. 또한 Perl, AWK 또는 sed 이외의 것을 사용하여 하는 방법에 대한 힌트를 제공하지 마십시오. 이 질문은 정말로 sed-only 질문입니다.

+0

최선을 다했습니다. 내 생각은 FROM 및 TO (여하튼)와 그 다음에 "어떻게 든"(나는 아직 어떻게 몰라서) 짝수 또는 홀수 부분에서만 또는 비슷하게 작동하도록 조각을 분할하는 것이 었습니다. 내가 그 일을하는 법을 알았다면 여기서 물어 보지 않았을 것입니다. 그리고, 분할에 대한 나의 아이디어가 잘못되었을 가능성이 높습니다. 그것은 꽤 어렵고 이전에는 sed를 간단한 작업에만 사용했습니다. – mjf

답변

1

나누고 정복하십시오.

줄 바꿈을 삽입하고 줄 바꿈, 줄 바꿈 (^), 줄 끝 ($) 및 구분 기호 (이 경우 괄호)를 앵커 및 루프로 사용하십시오. 추가 된 줄 바꿈은 결국 제거됩니다.

$ echo "A a A a (A a) A (a A) a" | 
    sed 's/([^)]*)/\n&/g; 
     :a; 
      s/\(\n([^)]*\)A\([^)]*)\)/\1T\2/; 
     ta; 
     s/\n//g' 
A a A a (T a) A (a T) a 
$ echo "F f F f (F f) F (f F) f" | 
    sed 's/(/\n(/g; 
     s/)/)\n/g; 
     :a; 
      s/\([^(]*\)F\([^)]*\(\n\|$\)\)/\1X\2/g; 
     ta; 
     s/\n//g' 
X f X f (F f) X (f F) f 
$ echo "1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q" | 
    sed 's/^/BAR/; 
     s/$/FOO/; 
     s/FOO/&\n/g; 
     s/BAR/\n&/g; 
     s/BAR[^\n]*\n//g; 
     s/[^\n]*FOO\n//g; 
     s/\n//g' 
d e f i j k 
+0

감사합니다. 잠시만 기다려주세요. 제발. – mjf

+0

"["및 "]"문자로 둘러싸인 섹션의 모든 부분을 정규 표현식 그대로 그대로 바꾸려면 어떻게해야합니까? 이 작업은 일반적인 정규 표현식 (모든 "() [] {+ |"문자를 이스케이프 할 필요가없는)을 특수 문자를 이스케이프해야하는 grep 또는 sed 표현식으로 변환하는 것과 비슷합니다. Sed 구문에서 이스케이프 처리해야하는 문자를 이스케이프 처리하지 않고 다음 sed 표현식을 사용하면 특수 문자가 만들어지기 때문에 다음 sed 프로그램의 AROUND 공간에 적용하고 싶습니다. "s/\\ ([] [() {} | +?] \\)/\\\ 1/g ". 입력 값은 "s/([] [() {} | +?])/\\\ 1/g"이 될 것입니다. – mjf

+0

BASIC POSIX 정규 표현식의 데이터베이스를 "^. [$() | * +? {\"문자를 "\"로 이스케이프시켜 "비 특별한"(맨 7 정규식)으로 만들어야하는 형식으로 유지합니다. 이 정규식을 주어진 순간에 필요한 형식으로 변환하는 스크립트가 필요합니다. 예를 들어 grep (1) 형식입니다. 그런 다음 sed (1) 형식이나 vi 편집기 형식 등이 필요합니다. 수동으로 정규 표현식을 변형하는 것은 고통스럽고 이제 db는 꽤 큰 크기로 커졌습니다. 모든 정규식을 수동으로 변환하려면 vi와 같은 영리한 편집기에서조차도 고통 스럽습니다. 그 일에 대한 대본이 필요합니다.이 질문에 대한 저의 원래 동기였습니다. – mjf

1

당신이 (GNU가 나오지도)에 대한이 작동 될 수 있습니다

sed ':a;s/\(([^)]*\)A/\1T/;ta' file # for case 1 

sed ':a;s/\(([^)]*\)F/\1\n/;ta;y/F\n/TF/' file # for case 2 

의 'T에의 괄호 안에'의 A을 대체 할 경우 (1 개) 사용 루프하십시오.

은 케이스 2의 '후, 개행 문자로의 괄호 안에 F 번역'의 F 변경 각각 X 년대와 F 년대에의 개행을 위해 상기와 동일하게 사용한다.

사례 3은 조금 더 복잡하지만,이 대체 명령을 수행 할 수 있습니다

sed -r 's/FOO|BAR/\n&/g;s/[^\n]*(\nBAR[^\n]*)*(\nFOO([^\n]*)\nBAR)?(\nFOO[^\n]*$)?/\3/g' file 

우선 접두사 줄 바꿈 각 FOOBAR 문자열. 그런 다음 FOOBAR의 모든 조합을 찾고 FOOBAR 사이의 문자열 만 유지하십시오. 개행을 사용하면 절차를 단순화하기 위해 음수 클래스를 사용할 수 있습니다.

관련 문제