grep을 사용하여 캐릭터의 위치를 ​​찾는 방법은 무엇입니까?


11

grep 명령을 사용하여 문자열에서 문자의 위치를 ​​식별해야합니다.

예를 들어 문자열은 RAMSITALSKHMAN|1223333입니다.

grep -n '[^a-zA-Z0-9\$\~\%\#\^]'

|주어진 문자열에서 위치를 어떻게 찾 습니까?


grep과 함께해야합니까?
Braiam

답변:


29

-b바이트 오프셋을 얻는 데 사용할 수 있습니다 . 이는 간단한 텍스트의 위치와 동일하지만 UTF-8 또는 이와 유사한 것은 아닙니다.

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|

위에서는 -a스위치를 사용하여 grep에게 입력을 텍스트로 사용하도록 지시합니다. 이진 파일을 조작 할 때 필요 -o하며 일치하는 문자 만 출력하는 스위치입니다.

위치 만 원하는 경우 grep을 사용하여 위치 만 추출 할 수 있습니다.

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14

이상한 출력이 나오면 grep에 색상이 활성화되어 있는지 확인하십시오. --colors=nevergrep 에 전달 하거나 grep 명령 앞에 접두사를 붙이면 색상을 비활성화 할 수 있습니다 \.

$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14

여러 개의 일치 항목을 반환하는 문자열의 head -n1경우 첫 번째 일치 항목을 얻기 위해 연결합니다.

위의 두 가지를 모두 사용하고, 별칭을 사용할 때만 grep이 실행 파일 (스크립트 또는 기타)을 통해 "별칭 화"되면 후자는 작동하지 않습니다.


3
이제 2;) 검색
Izkata

감사합니다 @Izkata, 당신이 맞아요. 내 게시물을 약간 업데이트하고 누락 된 모자를 추가했습니다 ^:)
runejuhl

1
어떤 버전의 grep을 사용 했습니까? 내가 얻을 0:|0 행의 시작 부분의 바이트 위치 때문에 output--로 |발견된다.
Alex

데비안에서 @Alex GNU grep stretch : grep (GNU grep) 2.27. 아마도 OS X를 사용하고 있습니까?
runejuhl

11

시험:

printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'

산출:

15:|

이렇게하면 인덱스 기반 -1의 위치가 제공됩니다.


작동하지 않습니다 :(
user82782

1
@ user82782 : 어떤 명령을 실행 했습니까? 작동하지 않는 것을 어떻게 알 수 있습니까?
cuonglm

printf '%s\n' '|' | grep -o . | grep -n '|'예상대로 인쇄 1하지 않습니다 0.
l0b0

1
@ l0b0 : OP는 인덱스베이스 0 또는 1을 원한다고 말하지 않습니다.
cuonglm

소프트웨어 개발자가 기대하는 바를 의미합니다.
l0b0

8

쉘을 사용하는 경우 또는 와 같은 외부 프로세스를 생성하지 않고도 순수하게 내장 된 작업을 사용할 수 있습니다 .

$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$ 

이것은 매개 변수 확장 을 사용하여 |모든 문자열 이 따르는 모든 발생을 제거 하고 임시 변수에 저장합니다. 그런 다음의 색인을 얻기 위해 임시 변수의 길이를 측정하는 것입니다 |.

(가) 주 if(가) 경우 확인되어 |원래 문자열의 모든 존재. 그렇지 않은 경우 임시 변수는 원래 변수와 동일합니다.

또한 이것은 0부터 시작하는 색인을 제공합니다.이 색인 |은 일반적으로 bash 문자열을 색인 할 때 유용합니다. 그러나 1 기반 색인이 필요한 경우 다음을 수행 할 수 있습니다.

$ echo $((${#tmp}+1))
15
$ 

1
아마 가장 좋은 대답은,이 구문은, 코어에 긴 라이브의 의미를 이해 할 때 사용하기 쉬운 아름답고 매우 빠르고입니다
vdegenne

4

awk index함수를 사용 하여 일치하는 문자의 위치를 ​​반환 할 수 있습니다 .

echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15

Perl의 index기능을 사용하지 않아도 될 경우 , 이것은 문자가 하나 이상 발생하는보고를 처리합니다.

echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'

가독성을 위해 파이프 라인은 두 줄로 나뉘어 있습니다.

대상 문자가 발견되면 index0을 기준으로 양수 값을 반환합니다. 따라서 문자열 "abc | xyz | 123456 | zzz |" 구문 분석시 위치 0, 4, 8, 15 및 19를 리턴합니다.


이 용도로 awk는 grep보다 더 유용합니다.
Archemar

이것은 첫 번째 위치 만 인쇄하며 다음과 같은 문자열에서는 작동하지 않습니다.RAMSITALSKHMAN|1|223333
cuonglm

3

"expr match"또는 "expr index"를 사용하여 수행 할 수도 있습니다.

expr match $ string $ substring 여기서 $ substring은 RE입니다.

echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`

그리고 위는 일치하는 부분 문자열의 길이를 반환하기 때문에 위치를 알려줍니다.

그러나 색인 검색에 대해 더 구체적으로 설명하십시오.

mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`

다른 곳에서는 논평 할만한 명성이 없습니다. @Gnouc의 답변을 개인적으로 좋아했습니다. 우리가 'expr에'를 사용하여 간단한 일을 할 수있다 그러나 왜 AWK를 사용하고 복잡한 만들려면
bluefoggy

@kingsdeb 그것은 단지 제안 일뿐입니다.
Avinash Raj

@kingsdeb : (1) awk파일의 모든 라인 에서이 정보를보고하기 위해 솔루션을 사소하게 수정할 수 있기 때문에 ( ENDJRFerguson의 답변에서 실제로 필요하지 않은을 제거하기 만하면됩니다 .Avinash Raj는 이미 수행합니다) ; 반면 expr솔루션으로 그렇게하려면 명시 적 루프를 추가해야합니다 (그리고 Gnouc의 대답은 쉽게 볼 수 없으며, 내가 볼 awk수 있음 ). (2) 솔루션은 모든 것을보고하도록 조정할 수 있습니다. 각 라인에서 expr솔루션 보다 다소 쉽게 일치 합니다 (사실 Avinash Raj의 솔루션도 이미 그렇게합니다).
G-Man, 'Reinstate

echo `...`여기서 사용 하겠습니까?
Stéphane Chazelas

여기에 출력을 보여주기위한 것입니다.
bluefoggy

2

또 다른 awk 명령 ,

$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15

필드 구분 기호를 null 문자열로 설정하면 awk는 레코드의 개별 문자를 별도의 필드로 바꿉니다.


2

일부 대안은 다음과 같습니다.

Gnouc의 답변과 비슷하지만 껍질이 있습니다.

echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n | 
sh

sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'

sed하고 dc가능한 여러 줄에 걸쳐 :

echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc

15

와 함께 $IFS...

IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))

그것은 또한 얼마나 많은지 알려줄 것입니다 ...

echo $(($#-1))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.