다음과 같은 텍스트 파일이 있습니다.
tech -this is sample and ... 1.2 sample
bla bla bla test tech 1 one two
foo bar foo bar tech and [email protected] 0.1
bar bar bar foo foo tech 10.1.3
tech 7.5 and continue this line
sample_test one two tech 8.0
one two there tech 0.x *sample bla bla
www sample tech 1.3.x foo bar $foo #bar
foobar barbar bla bla tech 5.x
tech testtest 2.0.4x this is sample
샘플 텍스트를 추출하고 싶습니다 - 다음과 같은 단어과학 기술그리고 이와 같은 숫자 패턴7.5및 기타 디지털 모드.
(실제로 숫자 패턴은 버전 제어 스타일 버전 번호입니다)
그런 다음 다음과 같이 출력을 얻습니다.
tech 1.2
tech 1
tech 0.1
tech 10.1.3
tech 7.5
tech 8.0
tech 0.x
tech 1.3.x
tech 5.x
tech 2.0.4x
답변1
가설
입력은 공백 문자 시퀀스(공백이 아닌 문자 시퀀스)로 구분된 문자열을 포함하는 텍스트 파일입니다. 각 줄에는 특정 단어(런타임에 알려짐)가 포함되어 있으며 그 뒤에는 버전 번호 형식의 숫자 문자열이 옵니다(즉시 필요하지는 않음). (분명히 이는 숫자로 시작한다는 의미입니다.)
런타임에 인수로 찾을 단어를 지정할 수 있어야 합니다. 예를 들어, 다음 단어를 검색하려면과학 기술, 우리는 말할 수 있어야합니다
word=tech
명령(또는 스크립트)이 를 사용하도록 합니다 $word
. 예를 들어 "technology", "nanotech" 및 "Tech"는 일치하지 않아야 합니다. 단어에는 문자, 숫자 및 _
(밑줄)(구두점, 정규 표현식의 특수 문자)만 포함되어야 하며 이로 인해 원치 않는 결과가 발생할 수 있습니다. 각 한정된 줄에 대해 명령은 공백으로 구분된 단어와 숫자를 출력해야 합니다. 파일에 이러한 가정을 충족하지 않는 줄이 포함되어 있으면(예: 필수 단어나 숫자가 포함되어 있지 않음) 동작이 정의되지 않습니다. 특히, 이러한 실패 라인은 간단히 무시할 수 있습니다.
아래의 모든 명령
$word
은 위와 같이 정의된 것으로 가정합니다.
참고: 이러한 각 명령은 서로 다른 방식으로 표현될 수 있습니다. 어떤 경우에는 그 차이가 미미합니다.
grep
분명히grep
나는 무엇을 해야할지 모르겠습니다.
간단 grep
하고 도움이 됨
주문하다
grep "\<$word\>\|\<[[:digit:]][[:graph:]]*\>"
다음을 포함하는 모든 줄과 일치합니다.누구나단어( \<$word\>
) 또는 ( \|
) 숫자( \<[[:digit:]][[:graph:]]*\>
). ( [[:graph:]]
문자, 숫자 또는 구두점, 즉 공백을 제외한 모든 문자를 나타냅니다.) --color
모드에서 이 명령의 출력은 약간 흥미롭습니다.
grep -o "\<$word\>\|\<[[:digit:]][[:graph:]]*\>"
일치하는 모든 문자열을 인쇄하고 일치하는 문자열만 인쇄합니다.끈— 별도의 줄에:
tech
1.2
tech
1
tech
0.1
tech
10.1.3
tech
7.5
tech
8.0
tech
0.x
tech
1.3.x
tech
5.x
tech
2.0.4x
그럼 우리는 이렇게 해요
grep -o "\<$word\>\|\<[[:번호:]][[:Graphic:]]*\>"(입력 파일)| sed "/$단어/ { N; s/\n/ / }"위의 출력을 얻고 단어를 연결합니다(과학 기술) 및 다음 줄(공백으로 구분):
tech 1.2
tech 1
tech 0.1
tech 10.1.3
tech 7.5
tech 8.0
tech 0.x
tech 1.3.x
tech 5.x
tech 2.0.4x
pcregrep
pcregrep -o1 -o2 --om-separator=' ' "\b($word)\b.*?\b(\d\S*)"
단어를 일치그리고숫자( \b
단어 경계,
\d
숫자, 공백을 제외한 모든 문자)는 ... 그룹 \S
에서 각각을 캡처합니다 . 그런 다음 일치하는 문자열만 출력 합니다 . 그러나 에서는 출력 캡처 그룹 1과 2 라고 말할 수 있습니다 . 당연히 문자열 사이에 무엇을 넣을지 지정하세요.(
)
-o
pcregrep
-o1 -o2
--om-separator=' '
참고: 여기서는 (탐욕적이지 않은 일치)를 사용하므로 .*?
입력 줄에 여러 숫자가 있는 경우 첫 번째 숫자가 검색됩니다. 다른 명령은 마지막 명령을 찾습니다.
sed
sed -n "s/.*\(\<$word\>\).*[[:blank:]]\(\<[[:digit:]][[:graph:]]*\).*/\1 \2/p"
해당 명령과 유사하게 pcregrep
이 명령은 캡처 그룹의 문자열을 일치시킨 다음 이를 \1 \2
.
awk
awk -v the_word="$word" '
{
w=0 # Index of word
n=0 # Index of number
for (i=0; i<=NF; i++) {
if ($i == the_word) w=i
if (substr($i,1,1) ~ /[[:digit:]]/) n=i
}
if (w>0 && n>w) print $w, $n
}'
the_word
그러면 단어( )와 숫자(첫 번째 문자가 숫자인 문자열)를 찾습니다 . 찾으면 순서대로 인쇄합니다.
참고: 단어는 완전히 독립된 경우에만 인식됩니다. 구두점에 도달하면 다른 명령도 이를 일치시킵니다.
The cyber clock goes tech, tock …
This contains the word (tech) …
답변2
아래 코드는 원하는 효과를 달성해야 합니다.
searchword="tech"
(cat << EOF
tech -this is sample and ... 1.2 sample
bla bla bla test tech 1 one two
foo bar foo bar tech and [email protected] 0.1
bar bar bar foo foo tech 10.1.3
tech 7.5 and continue this line
sample_test one two tech 8.0
one two there tech 0.x *sample bla bla
www sample tech 1.3.x foo bar $foo #bar
foobar barbar bla bla tech 5.x
tech testtest 2.0.4x this is sample
EOF
) | grep $searchword |\
grep -o '\b[0-9x][0-9x]*\b\|\b[0-9][0-9]*\.[0-9x][0-9x]*\b\|\b[0-9][0-9]*\.[0-9][0-9]*\.[0-9x][0-9x]*\b' |\
sed "s/^/$searchword /"
당신을 데려올 것이다
tech 1.2
tech 1
tech 0.1
tech 10.1.3
tech 7.5
tech 8.0
tech 0.x
tech 1.3.x
tech 5.x
tech 2.0.4x
적어도
- 세게 때리다
GNU bash, version 4.4.5(1)-release
- sed
sed (GNU sed) 4.2.2
- grep
grep (GNU grep) 2.27
이 답변이 도움이 되어 다행입니다. 그렇지 않으면 질문을 더 명확하고 설명하기 쉽게 고려할 수 있을 것입니다.
답변3
grep이나 sed에서는 이것을 얻을 수 없지만 Perl이 도움을 줍니다:
$ perl -e 'while($stdin = <>) {@matches = $stdin =~ /(tech)[^0-9]*([0-9x][0-9x.]*)/g; print "@matches\n" if @matches}' < INPUTFILE
이는 < INTPUTFILE
stdin을 통해 스크립트에 파일을 입력할 때만 작동합니다. stdin은 다른 소스(예: 파이프, <<<
문자열 리디렉션)에서 제공될 수 있습니다.
설명하다:
# 일치에 사용할 변수에 표준 입력(Perl)을 할당합니다. # 입력이 비어 있는 경우(예: EOF)를 감지합니다. 동안 ($stdin = ) { # @matches 배열에 $stdin에 일치 항목을 할당합니다. #/(기술)[^0-9]*([0-9x][0-9x.]*)/g; # (tech): "tech"라는 용어와 일치하고, ()는 @matches에 넣습니다. # [^0-9]*: .*가 너무 탐욕스럽기 때문에 숫자가 아닌 숫자와 일치하면 버려집니다. # 마지막 숫자와 일치 # ([0-9x][0-9x.]*): 0, 0.x, 0.9.x 등의 패턴을 일치시키고 () @matches에 넣습니다. @matches = $stdin =~ /(tech)[^0-9]*([0-9x][0-9x.]*)/g; # @matches가 비어 있지 않으면 위 배열을 표시합니다. @matches이면 "@matches\n"을 인쇄합니다. }
파일에 적용하면 출력은 다음과 같습니다.
기술 1.2 기술 1 기술 0.1 기술 10.1.3 기술 7.5 기술 8.0 기술 1.3.x 기술 5.x 기술 2.0.4x