예를 들어 다음과 같은 파일이 있습니다.
potato: 1234
apple: 5678
potato: 5432
grape: 4567
banana: 5432
sushi: 56789
로 시작하는 모든 줄에 대해 grep하고 potato:
있지만 뒤에 오는 숫자 만 파이프 하고 싶습니다 potato:
. 따라서 위의 예에서 출력은 다음과 같습니다.
1234
5432
어떻게 할 수 있습니까?
답변:
grep 'potato:' file.txt | sed 's/^.*: //'
grep
문자열이 포함 된 모든 줄을 potato:
찾은 다음 각 줄에 대해 줄의 시작 부분 ( )에서 시퀀스의 마지막 발생 (콜론 뒤에 공백이 있음 )까지 모든 문자 ( )를 빈 문자로 sed
바꿉니다 ( s///
-대체). 문자열 ( -첫 번째 부분을 비어있는 두 번째 부분으로 대체)..*
^
:
s/...//
또는
grep 'potato:' file.txt | cut -d\ -f2
포함 된 각 라인의 경우 potato:
, cut
공백으로 구분 된 여러 필드에 선 분할합니다 ( -d\
- d
= 구분 기호를, \
= 공백 문자, 같은 탈출 -d" "
(도 일한 것) 각각 같은 라인의 두 번째 필드를 인쇄 -f2
).
또는
grep 'potato:' file.txt | awk '{print $2}'
포함 된 각 라인에 대해 potato:
, awk
두 번째 필드 (인쇄 될 print $2
공간에 의해 디폴트로 구분된다).
또는
grep 'potato:' file.txt | perl -e 'for(<>){s/^.*: //;print}'
포함 된 모든 행은에서 모든 행을 가져 오는 potato:
인라인 ( -e
) Perl 스크립트 로 전송 된 stdin
다음 이러한 각 행에 대해 위의 첫 번째 예에서와 동일한 대체를 수행 한 다음 인쇄합니다.
또는
awk '{if(/potato:/) print $2}' < file.txt
이 파일을 통해 전송된다 stdin
( < file.txt
를 통해 파일의 내용을 전송 stdin
에 왼쪽에있는 명령에) awk
포함하는 각 라인, 해당 스크립트 potato:
( if(/potato:/)
정규 표현식이 경우 true를 반환 /potato:/
설명 된 바와 같이, 두 번째 필드를 현재 행을 일치), 인쇄 위.
또는
perl -e 'for(<>){/potato:/ && s/^.*: // && print}' < file.txt
파일은 stdin
( < file.txt
, 위 참조)를 통해 위의 것과 유사하게 작동하는 Perl 스크립트 로 전송 되지만 이번에는 각 행에 문자열이 포함되어 있는지 확인합니다 potato:
( /potato:/
현재 행 에이 포함 된 경우 일치하는 정규식 potato:
이고 ( &&
)를 수행 한 다음 위에서 설명한 정규식을 적용하고 결과를 인쇄합니다.
awk '/potato:/ {print $2}'
perl -pe
또는 정규식 어설 션을 사용하십시오. grep -oP '(?<=potato: ).*' file.txt
-o
은 행의 일치하는 부분 만 인쇄하는 것을 의미합니다. 반면 -P
에 Perl 호환 정규식을 유추하는 반면 regex를 긍정적으로 살펴(?<=string)
봅니다.
이것은 같은 줄에만 각 일치 후 모든 것을 인쇄합니다.
perl -lne 'print $1 if /^potato:\s*(.*)/' file.txt
이것은 모든 후속 행도 인쇄한다는 점을 제외하면 동일합니다.
perl -lne 'if ($found){print} elsif (/^potato:\s*(.*)/){print $1; $found++}' file.txt
다음 명령 줄 옵션이 사용됩니다.
-n
입력 파일의 각 줄을 반복-l
처리하기 전에 줄 바꿈을 제거하고 나중에 다시 추가합니다. -e
Perl 코드 실행 다른 답변 상태로 grep을 사용할 수 있습니다. 그러나 grep, awk, sed, perl, cut 또는 외부 도구는 필요하지 않습니다. 순수한 bash로 할 수 있습니다.
이것을 시도하십시오 (세미콜론은 당신이 그것을 모두 한 줄에 넣을 수 있도록 거기에 있습니다) :
$ while read line;
do
if [[ "${line%%:\ *}" == "potato" ]];
then
echo ${line##*:\ };
fi;
done< file.txt
## bash는 $ line에서 가장 긴 ":"일치를 맨 앞에서 삭제하도록 지시합니다.
$ while read line; do echo ${line##*:\ }; done< file.txt
1234
5678
5432
4567
5432
56789
또는 값 대신 키를 원하면 %%는 bash에게 $ line에서 가장 긴 일치 항목 인 ":"을 끝에서 삭제하도록 지시합니다.
$ while read line; do echo ${line%%:\ *}; done< file.txt
potato
apple
potato
grape
banana
sushi
분할 할 부분 문자열은 ": \"입니다. 공백 문자는 백 슬래시로 이스케이프되어야하기 때문입니다.
Linux 문서 프로젝트 에서 이와 유사한 것을 더 많이 찾을 수 있습니다 .
while read
매우 느립니다. 외부 유틸리티를 사용하는 것은 실제로 버퍼링 된 I / O가있는 것을 선택하는 한 훨씬 더 빠를 것입니다 (즉,이 답변에서 언급 한 것 중 하나와 다른 많은 것).
read -r
POSIX 이전의 다소 성가신 레거시 동작을 특별히 요구하지 않는 한 사용해야합니다 .
awk '$1 ~ /potato/ { print $2 }' file.txt
.