sed 캡처 그룹이 작동하지 않습니다


27

형식의 문자열이 [0-9]+\.[0-9]+\.[0-9]있습니다. 첫 번째, 두 번째 및 세 번째 숫자를 별도로 추출해야합니다. 내가 알기로는, 캡처 그룹이 이것을 할 수 있어야한다. sed "s/\([0-9]*\)/\1/g첫 번째 숫자 sed "s/\([0-9]*\)/\2/g를 얻고 두 번째 숫자 sed "s/\([0-9]*\)/\3/g를 얻고 세 번째 숫자 를 얻는 데 사용할 수 있어야합니다 . 각 경우에, 나는 전체 문자열을 얻고 있습니다. 왜 이런 일이 발생합니까?


6
캡처 그룹은 그룹의 개별 요소가 아닌 전체 그룹을 캡처합니다. 's/\([0-9]\)\([0-9]\)\([0-9]\).*/\1\2\3/'개별 숫자를 캡처하는 것과 같은 것이 필요 합니다.
Munir

답변:


45

우리는 귀하의 의견을 제시하지 않고 완전한 답변을 드릴 수는 없지만 캡처 그룹에 대한 이해가 잘못되었다고 말할 수 있습니다. 순차적으로 사용하지 않고 동일한 대체 연산자의 왼쪽에있는 정규식 만 참조합니다. 캡처 경우, 예를 들어 /(foo)(bar)(baz)/, 다음 foo\1, bar될 것입니다 \2baz있을 것입니다 \3. 당신은 할 수 없어 s/(foo)/\1/; s/(bar)/\2/, 두 번째에 있기 때문에, s///호출이 하나 개의 캡처 그룹이기 때문에 \2정의되지 않습니다.

따라서 세 자릿수 그룹을 캡처하려면 다음을 수행해야합니다.

sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'

또는 더 읽기 쉽습니다.

sed -E 's/([0-9]*)\.([0-9]*)\.([0-9]*)/\1 : \2 : \3/'

1
첫 번째 예에서 괄호를 피하면 어떤 이점이 있습니까?
Josh M.

2
@JoshM. 패턴을 캡처하는 데 사용 되려면 이스케이프해야합니다. 일반적으로 /(foo)/나오지에 리터럴 일치 (다음, 문자를 foo다음 문자 ). 그룹을 캡처하려면 괄호를 이스케이프하거나 -E옵션을 사용해야합니다 .
terdon

나는 거의 항상 -r플래그를 사용 하므로 이것이 아직 실행되지 않은 이유라고 생각합니다.
Josh M.

1
@JoshM. 예, -r깃발도 그렇게 할 것이지만 이식성이 없습니다. GNU sed는 그것을 지원하지만 다른 많은 사람들은 지원하지 않습니다. 은 -E더 보편적이다.
terdon

9

예:

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'
123

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'
456

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'
78

또는 모두 함께 :

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'
123 : 456 : 78

2

이스케이프 된 모든 괄호를 피하려면 -r, --regexp-extended와 함께 Sed를 사용하십시오.

echo "1234.567.89" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1, \2, \3/' 
1234, 567, 89    #output
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.