sed 또는 awk를 사용하여 개행 문자를 "조건부"로 제거하는 방법은 무엇입니까?

sed 또는 awk를 사용하여 개행 문자를 "조건부"로 제거하는 방법은 무엇입니까?

여러 줄이 포함된 파일이 주어지면 일부는 =끝에 있습니다.

=다음 줄로 끝나는 각 줄을 연결하고 싶습니다 . 다른 줄 바꿈은 변경하지 않고 그대로 두어야 합니다.

sed한 줄씩 수행되는 것 같아서 이 작업을 수행할 수 없었습니다 . 따라서 줄 바꿈은 항상 "추가"됩니다.

입력 예:

Apple
Banana milkshake
Cherry =
Pie

다음과 같아야 합니다:

Apple
Banana milkshake
Cherry Pie

나는 sed/ 이외의 도구를 사용하는 데 전적으로 개방적입니다 awk.

답변1

사용 awk:

$ awk '{ORS = sub(/=$/,"") ? "" : "\n"} 1' file
Apple
Banana milkshake
Cherry Pie

조건식을 사용하여 ORS(출력 레코드 구분 기호, 기본값: 개행)을 빈 문자열 또는 개행으로 설정합니다. sub()줄 끝에서 교체가 완료되면(기존 줄 제거) true이고 =, 그렇지 않으면 false입니다. 첫 번째 경우에는 ORS로 설정하고 "", 그렇지 않으면 로 설정합니다 "\n". 1행이 인쇄됨을 나타냅니다( ORS각 행에 대해 선택된 값 사용).


또는 sed파일이 메모리에 비해 그다지 크지 않고 충분히 작다고 가정하고 GNU 및 0으로 구분된 문자를 사용할 수 있습니다.

sed -z 's/=\n//g' file

sed전체 파일을 한 줄로 읽고 =\n모든 항목을 전역적으로 바꿉니다.

답변2

sed로 끝나는 줄을 감지 하는 데 사용됩니다 =. 그러한 줄이 발견되면 편집 버퍼의 현재 줄에 다음 줄이 추가되고 두 ​​줄을 구분하는 개행 문자가 추가되며 개행 문자 =와 개행 문자가 제거되고 연결된 줄이 인쇄됩니다.

$ cat file
Apple
Banana milkshake
Cherry =
Pie
$ sed '/=$/ { N; s/=\n//; }' file
Apple
Banana milkshake
Cherry Pie

이는 모두 로 끝나는 여러 연속 라인을 처리할 수 없다는 점에 유의하십시오 =. 이를 처리하려면 프로세스를 반복해야 합니다(중간 결과는 임시 파일, 원시 파일에 저장하거나 간단히 동일한 명령으로 다시 파이프할 수 있음).

...또는 다음에서 명시적인 루프를 수행할 수 있습니다 sed.

sed -e ':again' -e '/=$/ { N; s/=\n//' -e 'b again' -e '}' file

시험:

$ cat file
Apple
Banana milkshake
Pie =
with a cherry =
on top
$ sed -e ':again' -e '/=$/ { N; s/=\n//' -e 'b again' -e '}' file
Apple
Banana milkshake
Pie with a cherry on top

답변3

sed:

sed -e ':a' -e '$!N;s/=\n//;t a' -e 'P;D' file

GNU sed:

sed ':a;N;s/=\n//;ta;P;D' file

GNU awk:

awk '1' RS='=\n' ORS= file

진주:

perl -pe 's/=\n//' file

입력의 마지막 줄이 =<newline>awk로 끝나거나 Perl이 이를 삭제하면 sed는 삭제하지 않습니다.

답변4

=로 끝나는 각 줄을 다음 줄과 연결하고 싶습니다.

고쳐 쓰다

awk '/=$/ {line=line $0;sub(/=$/,"",line);next}{$0= line $0;print $0;line=""} END{if (line) print line}' file
Apple
Banana milkshake
Cherry Pie

=또한 다음 줄로 끝나는 각 줄(레코드)을 연결하거나 =모두 다음 줄로 끝나는 여러 연속 줄(녹음)을 연결하는 것도 테스트되었습니다 . 하나 이상의 줄이 =파일 끝에 있는지 여부(어디에서든)

이 코드는:

  • 코드의 첫 번째 부분(앞 next)은 행을 연결하여 =var에 저장하고 line이를 sub()또는 빈 문자열 =로 바꿉니다 ""(제거합니다).
  • 두 번째 부분(뒤 next)은 var의 내용을 line다음 줄(즉, 현재 레코드)과 연결하고 이를 인쇄한 후 var에 null 값을 할당합니다.
  • END 섹션은 레코드 또는 =파일 끝에 있는 레코드를 인쇄합니다.
  • 성명 next. 여기서 일치하지 않는 줄은 /=$/두 번째 코드 블록에 의해 처리됩니다. 그러나 파일이 한 줄(또는 그 이상)으로 끝나는 경우 =두 번째 코드 블록은 실행되지 않지만 END해당 섹션의 해당 줄을 인쇄할 수 있습니다.

예를 들어, 가상 레시피에 대해 다음 데이터를 사용하여 모든 것을 맛볼 수 있습니다.

cat supposed-recipe.txt 
Cherry Pie Smoothie. =
This cherry smoothie =
tastes just like...

Ingredients:
Greek yogurt, plain non-fat, =
unsweetened milk, =
unsalted cashews,  =
etc.

And also:
1 pinch salt, =
and oats.
1 teaspoon =
vanilla extract,
fresh =
lemon juice.
1 teaspoon =
cinnamon, =
and frozen =
sweet cherries.

Optional:
2 teaspoons =
syrup or honey, =
to sweeten if wanted.

...and, if you want,
1 teaspoon chia seeds =
or similar. =
awk '/=$/ {line=line $0;sub(/=$/,"",line);next}{$0= line $0;print $0;line=""} END{if (line) print line}' supposed-recipe.txt

Cherry Pie Smoothie. This cherry smoothie tastes just like...

Ingredients:
Greek yogurt, plain non-fat, unsweetened milk, unsalted cashews,  etc.

And also:
1 pinch salt, and oats.
1 teaspoon vanilla extract,
fresh lemon juice.
1 teaspoon cinnamon, and frozen sweet cherries.

Optional:
2 teaspoons syrup or honey, to sweeten if wanted.

...and, if you want,
1 teaspoon chia seeds or similar.

관련 정보