Bash 또는 쉘 스크립트를 사용하고 교체하고 싶습니다아무것두 괄호 사이에 공백이 있습니다. 두 괄호 사이의 텍스트는 여러 줄이 될 수 있습니다. 예를 들면 다음과 같습니다.
myFunction (line0
line1
line2
line3
line4)
다음으로 변환하고 싶습니다.
myFunction ( )
답변1
@Serg의 답변을 받아 bash
한 줄에 2~3개의 프로세스 대신 bash 내장 기능을 사용하도록 변환하세요. 이 과정은 저렴하지만 무료는 아닙니다!
#!/bin/bash
# Use shell builtins, read, true, false, printf
flag=false
while IFS= read -r line
do
case "$line" in
(*"("*) flag=true ;;
esac
if $flag
then
line=${line//line/newline}
fi
printf "%s\n" "$line"
case "$line" in
(*")"*) flag=false ;;
esac
done < "$1"
답변2
AWK
{}
AWK를 사용하면 다양한 조건에서 코드 블록을 실행할 수 있습니다. 이 경우에는 gsub()
Contains (
에서 Contains 까지 의 행 범위에서 각 행을 실행하려고 합니다 )
.
$ awk '$0~/[(]/,$0~/[)]/{gsub(/line/,"newline")};1' input.txt
another line
something else
myFunction (newline0
newline1
whatever
newline2
newline3
newline4)
some other line
Python (원래 답변)
다음은 작업을 수행하는 빠른 Python 스크립트입니다.
#!/usr/bin/env python3
from __future__ import print_function
import sys
with open(sys.argv[1]) as fp:
flag = None
for line in fp:
clean_line = line.strip()
if "(" in clean_line: flag = True
if flag:
clean_line = clean_line.replace("line","newline")
print(clean_line)
if ")" in clean_line: flag = False
테스트 실행:
$ cat input.txt
another line
something else
myFunction (line0
line1
lilne2
line3
line4)
some other line
$ ./edit_function_args.py input.txt
another line
something else
myFunction (newline0
newline1
newline2
newline3
line4)
some other line
배쉬 버전
bash
다음 과 같이 다시 작성된 것을 제외하고 동일한 스크립트sed
#!/bin/bash
flag=false
while IFS= read -r line
do
if grep -q '(' <<< "$line"
then
flag=true
fi
if $flag
then
line=$(sed 's/line/newline/' <<< "$line")
fi
printf "%s\n" "$line"
if grep -q ')' <<< "$line"
then
flag=false
fi
done < "$1"
답변3
perl
해결 방법이 괜찮고 파일이 전체적으로 처리될 만큼 작은 경우 :
$ perl -0777 -pe 's/\([^)]+\)/$&=~s|line|newline|gr/ge' ip.txt
myFunction (newline0
newline1
newline2
newline3
newline4)
-0777
전체 입력 파일을 먹어라\([^)]+\)
일치시킬 패턴 - 문자(
가 아닌 문자가 오고)
다음으로 끝납니다.)
$&=~s|line|newline|gr
인용된 패턴이 여기에서 사용되며$&
필요한 대체(줄 바꾸기에서 줄 바꿈)가 수행됩니다.r
결과를 대체 문자열로 반환하는 플래그에 유의하세요.e
플래그를 사용하면 문자열 대신 표현식을 사용할 수 있습니다.perl -i -0777 -pe
내부 편집 용
답변4
사용
awk
:
awk '
function mysub(str) {
if (str) gsub(/line/, "newline", str); return str
}
BEGIN {
OFS=FS="("
}
NF>1 {
if (FS=="(") {
print $1,mysub($2); OFS=FS=")"
} else {
print mysub($1),$2; OFS=FS="("
}
next
}
{
print FS=="(" ? $0 : mysub($0)
}' /path/to/input
사용자 정의 함수는 mysub
대괄호 사이에 필요한 대체를 수행하는 곳입니다. 대괄호가 중첩되지 않았다고 가정합니다.
괄호 내부와 외부 괄호의 두 가지 상태가 있습니다.
- 외부적으로(시작 상태) 입력 및 출력 구분 기호는 왼쪽 대괄호(
OFS=FS="("
)로 설정됩니다. - 입력 구분 기호( )로
NF>1
구분된 여러 필드가 포함된 줄을 만나면...- ...현재 외부 모드( )에 있으며
FS=="("
필드 구분 기호 앞과 뒤의 모든 내용이 출력되지만(출력 구분 기호는 중간에 있음) 후자는 대체 기능(mysub($2)
)을 거쳐 모드와 출력 구분 기호를 뒤집습니다. 입력 기호(OFS=FS=")"
)를 변경하여, - ...그렇지 않으면(
else
) 내부 모드에 있고 필드 구분 기호 전후의 모든 내용이 출력되지만 이번에는 전자가 대체 기능(mysub($1)
)을 거치고 여기에서도 모드가 반전됩니다.
- ...현재 외부 모드( )에 있으며
- 다른 모든 라인에서 외부( )이면 전체 라인이 변경되지 않고 출력되고,
FS=="("
그렇지 않으면 대체 함수( )를 통해 전체적으로 전달됩니다mysub($0)
.
awk 'function m(s){gsub(/line/,"newline",s);return s}BEGIN{OFS=FS="("}NF>1{if(FS=="("){print $1,m($2);OFS=FS=")"}else{print m($1),$2;OFS=FS="("}next}{print FS=="("?$0:m($0)}' /path/to/input
내 까다로운 테스트 데이터(여기서 일부 한 줄 솔루션은 실패함):
line96
line97 myFunction (line0
line1
line2
line3
line4) line98
line99
출력:
line96
line97 myFunction (newline0
newline1
newline2
newline3
newline4) line98
line99
대괄호 사이의 모든 내용을 제거하는 변형입니다(첫 번째 줄과 마지막 줄 바꿈 제외):
awk '
BEGIN {
OFS=FS="("
}
NF>1 {
if (FS=="(") {
print $1,""; OFS=FS=")"
} else {
print "",$2; OFS=FS="("
}
next
}
FS=="("' /path/to/input
이 출력은 다음과 같습니다.
line96
line97 myFunction (
) line98
line99