ed(1)로 이 정규식 범위를 인쇄할 수 없는 이유는 무엇입니까?

ed(1)로 이 정규식 범위를 인쇄할 수 없는 이유는 무엇입니까?

ed를 사용하여 이 범위를 인쇄할 수 없는 이유가 완전히 혼란스럽습니다.범위가 2개인 경우-바라보다파일 2.tf파일-;하지만 인쇄할 수 있는 경우는 다음과 같습니다.범위-바라보다파일 1.tf파일 - gsed(macOS에서는 GNU sed) 명령을 사용하여 인쇄할 수 있지만 ed로는 인쇄할 수 없습니다. 내 쉘 세션을 고려하여 내 오해를 명확히 해주십시오.

$ ed -s file1.tf <<<',n'
1   # some comment
2   module "hello_world" {
3     source = "./mydir"
4   }
5   # another comment
$ ed -s file1.tf <<<'/module.*world/,/}/p'
module "hello_world" {
  source = "./mydir"
}
$ ed -s file2.tf <<<',n'
1   # some comment
2   module "hello_world" {
3     source = "./mydir"
4   }
5   # another comment
6   # some comment
7   module "hello_again" {
8     source = "./anotherdir"
9   }
10  # another comment
$ ed -s file2.tf <<<'/module.*again/,/}/p'
?
$ gsed -n '/module.*again/,/}/p' file2.tf
module "hello_again" {
  source = "./anotherdir"
}

업데이트: 반대 방향이 작동하지만 이유는 모르겠습니다.

$ ed -s file2.tf <<<'?module.*again?,?}?p'
module "hello_again" {
  source = "./anotherdir"
}

업데이트 2: 이 ??방법은 실제로 예상대로 작동하지 않습니다.세 부분그림파일 3.tf파일 예) 설명은 답변을 참조하세요.

$ ed -s file3.tf <<<,n
1   # some comment
2   module "hello_world" {
3     source = "./mydir"
4   }
5   # another comment
6   # some comment
7   module "hello_again" {
8     source = "./anotherdir"
9   }
10  # another comment
11  # some comment
12  module "hello_yet_again" {
13    source = "./yetanotherdir"
14  }
15  # another comment
$ ed -s file3.tf <<<'?module.*hello_again?,?}?p'
module "hello_again" {
  source = "./anotherdir"
}
# another comment
# some comment
module "hello_yet_again" {
  source = "./yetanotherdir"
}

답변1

문제를 일으키는 와 의 차이점 ed은 정규식 주소 범위가 처리되는 방식입니다.sed

에서는 sed먼저 시작 줄을 찾은 다음 끝 줄을 찾을 때까지 모든 줄에 명령이 적용됩니다.

ed반면에 에서는 범위의 시작 및 끝 선이 현재 행을 기준으로 계산됩니다. 그러면 해당 라인 범위 내의 모든 라인에 명령이 적용됩니다.

/module.*again/, /}/in 및 두 번째 file 을 사용하는 경우 ed현재 줄은 파일 끝에 있습니다(방금 버퍼에 로드했기 때문입니다). 범위의 시작 라인은 라인 7로 평가되고 종료 라인은 라인 4(두 번째 표현식과 일치하는 현재 라인 다음의 첫 번째 라인)입니다. 뒤로 실행되는 범위를 가질 수 없으므로 오류가 발생합니다.

를 사용하면 ?module.*again?, ?}?검색이 반대로 작동하므로 범위의 시작은 이전과 같이 7행으로 계산되지만(한 행만 표현식과 일치함 module.*again) 이제 범위의 끝은 7보다 큰 9행이므로 같은 질문이 아닙니다.

귀하의 솔루션은아니요?정규식 구분 기호 대신 in 을 사용하여 검색을 반대로 하면 /세 부분 중 중간을 올바르게 찾을 수 없습니다(예제에는 두 부분만 있음). 대신 먼저 커서를 범위의 첫 번째 줄로 이동한 다음 해당 줄에서 섹션 끝까지 명령을 적용하세요.

/module.*again/; /}/ p

이는 와 매우 유사해 보이지만 대신 을 /module.*again/, /}/ p사용하면 시작 주소를 찾을 때까지 끝 주소가 계산되지 않습니다. 이는 다른 선택의 여지가 없기 때문에(전체 문서를 메모리에 저장하지 않음) 범위를 처리하는 기본 방법입니다.;,sed

이 표현식은 기본적으로 커서를 범위의 시작 부분으로 명시적으로 이동한 다음 현재 현재 줄에서 섹션 끝까지 명령을 적용하는 더 긴 표현식과 동일합니다.

/module.*again/; ., /}/ p

POSIX 사양ed,vs에 대해 말하는 내용은 다음과 같습니다 ;.

<comma>,주소는 ( ) 또는 <semicolon>문자 ( ) 로 구분해야 합니다 ;. 구분 기호 가 있는 경우 <semicolon>현재 행( .)은 두 번째 주소가 계산되기 전에 첫 번째 주소로 설정됩니다. 이 기능은 정방향 및 역방향 검색의 시작선을 결정하는 데 사용할 수 있습니다.

관련 정보