foo.txt 파일이 있습니다.
test
qwe
asd
xca
asdfarrf
sxcad
asdfa
sdca
dac
dacqa
ea
sdcv
asgfa
sdcv
ewq
qwe
a
df
fa
vas
fg
fasdf
eqw
qwe
aefawasd
adfae
asdfwe
asdf
era
fbn
tsgnjd
nuydid
hyhnydf
gby
asfga
dsg
eqw
qwe
rtargt
raga
adfgasgaa
asgarhsdtj
shyjuysy
sdgh
jstht
ewq
sdtjstsa
sdghysdmks
aadfbgns,
asfhytewat
bafg
q4t
qwe
asfdg5ab
fgshtsadtyh
wafbvg
nasfga
ghafg
ewq
qwe
afghta
asg56ang
adfg643
5aasdfgr5
asdfg
fdagh5t
ewq
qwe와
ewq` 사이의 모든 줄을 별도의 파일에 인쇄하고 싶습니다.
이것이 지금까지 제가 가진 것입니다:
#!/bin/bash
filename="foo.txt"
#While loop to read line by line
while read -r line
do
readLine=$line
#If the line starts with ST then echo the line
if [[ $readLine = qwe* ]] ; then
echo "$readLine"
read line
readLine=$line
if [[ $readLine = ewq* ]] ; then
echo "$readLine"
fi
fi
done < "$filename"
스크립트를 몇 가지 변경해야 합니다(특별한 순서 없이):
read
앞에 IFS=
를 사용합니다.은 어디에서도 변경되지 않으므로 변수
readLine`이 필요하지 않습니다.이렇게 변경하면 스크립트가 됩니다:
#!/bin/bash
filename="foo.txt"
#While loop to read line by line
while IFS= read -r line; do
#If the line starts with ST then set var to yes.
if [[ $line == qwe* ]] ; then
printline="yes"
# Just t make each line start very clear, remove in use.
echo "----------------------->>"
fi
# If variable is yes, print the line.
if [[ $printline == "yes" ]] ; then
echo "$line"
fi
#If the line starts with ST then set var to no.
if [[ $line == ewq* ]] ; then
printline="no"
# Just to make each line end very clear, remove in use.
echo "----------------------------<<"
fi
done < "$filename"
이렇게 압축할 수 있습니다:
#!/bin/bash
filename="foo.txt"
while IFS= read -r line; do
[[ $line == qwe* ]] && printline="yes"
[[ $printline == "yes" ]] && echo "$line"
[[ $line == ewq* ]] && printline="no"
done < "$filename"
그러면 시작 줄과 끝 줄(포함)이 인쇄됩니다.
인쇄할 필요가 없는 경우 시작 테스트와 끝 테스트를 서로 바꾸면 됩니다:
#!/bin/bash
filename="foo.txt"
while IFS= read -r line; do
[[ $line == ewq* ]] && printline="no"
[[ $printline == "yes" ]] && echo "$line"
[[ $line == qwe* ]] && printline="yes"
done < "$filename"
그러나 readarray
를 사용하고 배열 요소로 반복하는 것이 훨씬 더 좋습니다(bash 버전 4.0 이상을 사용하는 경우):
#!/bin/dash
filename="infile"
readarray -t lines < "$filename"
for line in "${lines[@]}"; do
[[ $line == ewq* ]] && printline="no"
[[ $printline == "yes" ]] && echo "$line"
[[ $line == qwe* ]] && printline="yes"
done
그러면 read
를 사용할 때 발생하는 대부분의 문제를 피할 수 있습니다.
물론, (댓글에서 권장하는, 고마워요, @costas) sed
줄을 사용하여 처리할 줄만 가져올 수도 있습니다:
#!/bin/bash
filename="foo.txt"
readarray -t lines <<< "$(sed -n '/^qwe.*/,/^ewq.*/p' "$filename")"
for line in "${lines[@]}"; do
: # Do all your additional processing here, with a clean input.
done
코스타스가 지적했듯이, 이 작업에 사용할 올바른 도구는 sed
입니다:
sed '/qwe/,/ewq/ w other.file' foo.txt
인쇄할 줄에 다른 처리가 필요할 수 있습니다. 괜찮습니다. 그냥 그렇게 하세요:
sed -e '/qwe/,/ewq/{w other.file' -e 'other processing;}' foo.txt
(물론, <다른 처리>는 실제 sed
명령이 아닙니다.) 위의 패턴은 줄을 인쇄한 후에 처리를 수행해야 하는 경우 사용할 수 있는 패턴입니다. 다른 처리를 수행한 다음 변경된 버전의 줄을 인쇄하려는 경우(더 가능성이 높아 보입니다) 사용합니다:
sed -e '/qwe/,/ewq/{processing;w other.file' -e '}' foo.txt
(}
를 자체 인수에 넣어야 합니다. 그렇지 않으면 other.file
이름의 일부로 해석됩니다.)
당신(OP)은 줄에 어떤 '다른 처리'를 해야 하는지 명시하지 않았거나 더 구체적으로 말할 수 있습니다. 그러나 그 처리가 무엇이든 sed
에서 수행 할 수 있으며, 너무 다루기 힘들면 위의 코드를 거의 변경하지 않고 awk
에서 수행 할 수 있습니다:
awk '/qwe/,/ewq/ { print > "other.file" }' foo.txt
그러면 awk
프로그래밍 언어의 모든 기능을 마음대로 사용하여 print
문을 실행하기 전에 줄에서 처리를 수행할 수 있습니다. 물론 awk
(및 sed
)는 bash
와 달리 텍스트 처리를 위해 설계되었습니다.
qwe(){ printf %s\\n "$1"; }
ewq(){ :; }
IFS= ### prep the loop, only IFS= once
while read -r in
do case $in in
(qwe|ewq)
set "$in"
;;
("$processing"?)
"$process"
esac
"$1" "$in"
done
이는 매우 느린 방법 중 하나입니다. GNU grep
와 일반 인파일
을 사용합니다:
IFS=
while grep -xm1 qwe
do while read -r in &&
[ ewq != "$in" ]
do printf %s\\n "$in"
: some processing
done
done <infile
...적어도 비효율적인 읽기의 절반을 최적화할 수 있습니다...
sed -ne '/^qwe$/,/^ewq$/H;$!{/^qwe$/!d;}' \
-e "x;s/'"'/&\\&&/g;s/\n/'"' '/g" \
-e "s/\(.*\) .e.*/p '\1/p" <input |
sh -c 'p(){ printf %s\\n "$@"
for l do : process "$l"
done
}; . /dev/fd/0'
그러면 대부분의 sh
에 대해 read
의 비효율성을 완전히 피할 수 있지만, 출력을 두 번(한 번은 sh
에 따옴표로 묶고 한 번은 따옴표로 묶지 않은 상태로 stdout에 출력해야 합니다) 인쇄해야 합니다. 대부분의 구현에서 .
명령은 바이트 단위가 아닌 블록 단위로 입력을 읽는 경향이 있기 때문에 다르게 작동합니다. 그래도 이 명령은 ewq - qwe를 완전히 생략하며, FIFO와 같은 스트리밍 입력에 대해 작동합니다.
qwe
asd
xca
asdfarrf
sxcad
asdfa
sdca
dac
dacqa
ea
sdcv
asgfa
sdcv
qwe
a
df
fa
vas
fg
fasdf
qwe
aefawasd
adfae
asdfwe
asdf
era
fbn
tsgnjd
nuydid
hyhnydf
gby
asfga
dsg
qwe
rtargt
raga
adfgasgaa
asgarhsdtj
shyjuysy
sdgh
jstht
qwe
asfdg5ab
fgshtsadtyh
wafbvg
nasfga
ghafg
qwe
afghta
asg56ang
adfg643
5aasdfgr5
asdfg
fdagh5t