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

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

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

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

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



답변

-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이 실행 파일 (스크립트 또는 기타)을 통해 “별칭 화”되면 후자는 작동하지 않습니다.


답변

시험:

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

산출:

15:|

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


답변

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

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

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

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

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

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


답변

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를 리턴합니다.


답변

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

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

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

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

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

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


답변

또 다른 awk 명령 ,

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

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


답변

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

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))