programing

셸 스크립팅에서 문자열의 처음 두 문자를 추출하려면 어떻게 해야 합니까?

elseif 2023. 4. 29. 08:48

셸 스크립팅에서 문자열의 처음 두 문자를 추출하려면 어떻게 해야 합니까?

예를 들어, 다음과 같습니다.

USCAGoleta9311734.5021-120.1287855805

다음과 같이 추출합니다.

US

아마도 가장 효율적인 방법일 것입니다, 만약 당신이 그것을 사용한다면.bash셸(그리고 당신의 주석에 따르면 당신은)은 매개 변수 확장의 하위 문자열 변형을 사용하는 것입니다.

pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US

이것은 설정될 것입니다.short 물되는이인의 첫 두 것long.한다면long두문보자 다 짧 습 니 다 니 짧short그것과 동일할 것입니다.

일반적으로 이 인셸 방법은 프로세스 생성 오버헤드가 없기 때문에 보고서당 50,000회 정도의 작업을 자주 수행하는 경우에 더 좋습니다.외부 프로그램을 사용하는 모든 솔루션은 이러한 오버헤드로 인해 어려움을 겪을 것입니다.

또한 최소 길이를 보장하려면 다음과 같은 방법으로 미리 패드를 넣을 수 있습니다.

pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.

이렇게 것이 마침표로 수 ▁used▁creating▁this▁character▁the를▁when,▁by▁else▁changing▁(▁would▁ensure다이▁charact▁padded▁on▁less▁justorers패니것(▁was▁periods렇▁that▁anything▁with됩오표▁in▁something딩▁the▁two). 생성 시 사용되는 문자를 변경하는 것만으로tmpstr) 완성도를 이것이 필요한지 확실하지 않지만 완성도를 위해 넣으려고 생각했습니다.


외부 를 들어, 하외예프이로으수방램있다여습니가경우가지러법은는행그하작없업렇는긴지을만로그부예▁having▁you▁(▁as▁if▁programs▁there▁don▁that(,such▁said▁to우경▁with다▁havet: ▁this▁external▁any는없니습있그▁are▁do▁number렇)bash사용 가능), 그 중 일부는 다음과 같습니다.

short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')

두개 (처음두개개(두▁the처▁(▁first음)cut그리고.head는 한 문자열에 . 으로 둘 다 두 는 한 줄의 문자열에 대해 동일합니다. 기본적으로 둘 다 처음 두 문자만 반환합니다.는 점에서 차이가 있습니다.cut각 행의 처음 두 문자를 제공합니다.head 전체 의 첫 두 가 나옵니다.

세 번째는 다음을 사용합니다.awk두하는 서브 문자열 와 네 를 사용하는 서브 문자열 함수입니다.sedgroups ()()그리고.\1두하고 전체 행을 로 바꿉니다 처음 두 문자를 캡처하고 전체 행을 이 문자로 바꿉니다.은 둘 다 비슷합니다.cut입력에서 각 행의 처음 두 문자를 전달합니다.

입력이 한 줄로 되어 있다고 확신할 경우 모두 동일한 효과를 얻을 수 있습니다.

가장 쉬운 방법은 다음과 같습니다.

${string:position:length}

이 추된위치를 추출하는 곳.$length에 된파생에서 된 문자열$string$position.

이것은 내장된 Bash이므로, 어색하거나 sed가 필요하지 않습니다.

가지 때문에 저도 배쉬 , 이 당은몇 가좋답얻나었고을는내로것다이내후이질배가당한문하선지신이신장만택쉬할된를지은▁about▁you▁you▁asked▁builtin로이,▁myself▁with▁but▁bash당▁and후▁the질▁since신한▁i▁good''▁several.sed그리고.awk그리고 (거의) 아무도 이를 기반으로 한 솔루션을 제공하지 않았습니다. 저는 다음과 같이 제안합니다.

echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,1,2)}'

그리고.

echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'

awk하나는 꽤 분명해야 하지만, 여기에 대한 설명이 있습니다.sed아래쪽:

  • 대체 "s/"
  • 행 "^"의 시작 부분에서 시작하여 "."가 이어지는 두 문자의 그룹("), "."이 0회 이상 반복됨(일부 특수 문자를 이스케이프하려면 백슬래시가 필요함)
  • 첫 번째(그리고 이 경우에만 해당) 그룹의 내용 "/"에 의해(여기서 백슬래시는 일치하는 하위 표현을 참조하는 특수 이스케이프입니다).
  • 완료 "/"

그냥 grep:

echo 'abcdef' | grep -Po "^.."        # ab

만약 당신이 참여한다면bash다음과 같이 말할 수 있습니다.

bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab

이것이 바로 여러분이 필요로 하는 것일 수도 있습니다.

셸 스크립팅을 사용하고 비포식스 확장(예: 바시즘)에 의존하지 않으려면 grep, sed, cut, awk 등과 같은 포킹 외부 도구가 필요 없는 기술을 사용하면 스크립트의 효율성이 떨어집니다.사용 사례에서 효율성과 posix 휴대성은 중요하지 않을 수 있습니다.그러나 이 경우(또는 좋은 습관일 경우) 다음 매개 변수 확장 옵션 방법을 사용하여 셸 변수의 처음 두 문자를 추출할 수 있습니다.

$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab

이것은 "가장 작은 접두사" 매개 변수 확장을 사용하여 처음 두 문자를 제거합니다.${var#??}part), 그 다음 "확장 접미사" 매개 변수 확장(the${var%part에서 처음 두를 제외한 모든 합니다.

이 방법은 이전에 "Shell = Check if variable이 #로 시작하는지 확인" 질문에 대한 답변에서 설명했습니다.이 대답은 또한 여기서 원래 질문에 적용되는 것과 약간 다른 맥락에서 사용될 수 있는 몇 가지 유사한 매개 변수 확장 방법을 설명합니다.

사용할 수 있습니다.printf:

$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US

colrm — 파일에서 열 제거

처음 두 개의 문자를 남기려면 3부터 시작하는 열만 제거합니다.

cat file | colrm 3

사용:

sed 's/.//3g'

또는

awk NF=1 FPAT=..

또는

perl -pe '$_=unpack a2'

단지 재미를 위해 저는 그것들이 너무 복잡하고 쓸모가 없지만, 언급되지 않았다는 것을 몇 가지 덧붙입니다.

head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')

echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none

sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')

cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')

python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"

ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'

셸을 하고 있는 (not 시에서사다셸사경는우하용경우않는지용을하스른템사▁if(경▁(▁a▁your▁isnot)경)bash), 에는 ), "는 다음과 같은 기능이 있습니다bash그러면 당신은 여전히 고유한 문자열 조작을 사용할 수 있습니다.bashbash변수 포함:

strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"

유니코드 + UTF-8을 고려하는 방법

바이트가 아닌 유니코드 문자에 관심이 있는 사용자를 대상으로 간단한 테스트를 수행해 보겠습니다.의 각 문자áéíóúUTF-8에서는 2바이트로 구성되어 있습니다.

printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'
printf 'áéíóú' | LC_CTYPE=C awk '{print substr($0,1,3);exit}'
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 head -c3
echo
printf 'áéíóú' | LC_CTYPE=C head -c3

다음을 확인:

áéí
á
á
á

그래서 우리는 그것만 봅니다.awk+LC_CTYPE=en_US.UTF-8UTF-8 문자로 간주됩니다.다른 접근 방식은 3바이트만 소요되었습니다.다음을 통해 확인할 수 있습니다.

printf 'áéíóú' | LC_CTYPE=C head -c3 | hd

이는 다음을 제공합니다.

00000000  c3 a1 c3                                          |...|
00000003

리고그고.c3그 자체가 쓰레기이고, 터미널에 나타나지 않기 때문에, 우리는 단지 보았습니다.á.

awk+LC_CTYPE=en_US.UTF-8하지만 실제로는 6바이트를 반환합니다.

또한 다음을 사용하여 동등한 테스트를 수행할 수도 있습니다.

printf '\xc3\xa1\xc3\xa9\xc3\xad\xc3\xb3\xc3\xba' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'

일반 매개 변수를 원하는 경우:

n=3
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 awk "{print substr(\$0,1,$n);exit}"

유니코드 + UTF-8에 대한 더 구체적인 질문: https://superuser.com/questions/450303/unix-tool-to-output-first-n-characters-in-an-utf-8-encoded-file

관련: https://unix.stackexchange.com/questions/3454/grabbing-the-first-x-characters-for-a-string-from-a-pipe

Ubuntu 21.04에서 테스트되었습니다.

이것이 당신이 추구하는 것일 수도 있습니다.

my $string = 'USCAGoleta9311734.5021-120.1287855805';

my $first_two_chars = substr $string, 0, 2;

참조: 하위 항목

perl -ple 's/^(..).*/$1/'

코드

if mystring = USCAGoleta9311734.5021-120.1287855805

    print substr(mystring,0,2)

미국을 인쇄할 것입니다.

여기서 0은 시작 위치이고 2는 읽을 문자 수입니다.

언급URL : https://stackoverflow.com/questions/1405611/how-can-i-extract-the-first-two-characters-of-a-string-in-shell-scripting