머리와 꼬리만 사용하여 문자열의 일부 추출

머리와 꼬리만 사용하여 문자열의 일부 추출

안녕하세요. 헤드, 테일, 파이프(결국 리디렉션)만 사용하여 문자열의 시작, 중간, 끝을 추출하고 출력하는 방법이 있는지 궁금합니다.

예: 다음 문자열이 주어지면 SHOWpijfirefjTHISezpijSTRING명령은 'SHOWTHISSTRING'을 출력해야 합니다.

나는 다음과 같은 것을 시도했습니다 (head -c 4 mdp > /dev/tty) | (tail -c +13 mdp | head -c 4 > /dev/tty) | (tail -c 6 mdp > /dev/tty) 2>&1

그러나 항상 동일한 결과를 반환하는 것은 아니며 순서가 지정되지 않은 결과를 제공할 수도 있습니다.

답변1

head비표준 -c옵션을 지원하고 고정된 바이트 수를 출력하라는 요청을 받았을 때 입력에서 필요한 것보다 더 많이 읽지 않을 만큼 스마트한 구현을 사용할 수 있습니다 .

string='SHOWpijfirefjTHISezpijSTRING'
printf %s "$string" | {
  head -c 4
  head -c 9 > /dev/null
  head -c 4
  tail -c 6
}

headGNU 의 head내장 함수 에서는 작동 ksh93하지만 headbusybox에서는 작동하지 않는 방법을 확인하세요 . 을 실행하면 strace -fe read busybox sh ./that-script다음이 표시됩니다.

[pid  7739] read(0, "SHOWpijfirefjTHISezpijSTRING", 4096) = 28

첫 번째는 head전체 블록을 읽어 모든 입력을 소비하고 그 중 4바이트를 출력하므로 다음 head및 명령에 대해 tail읽을 수 있는 내용은 남지 않습니다 .

GNU 또는 ksh93을 사용하는 경우 head:

[pid 10293] read(0, "SHOW", 4)          = 4

또한 문자 1 대신 바이트 headtail사용되므로 -c고정된 수의 문자를 보고하는 데만 사용할 수 있으며 텍스트는 문자당 1바이트로 인코딩됩니다.

대부분의 최신 셸에는 문자 위치를 기준으로 문자열을 분할하는 연산자가 내장되어 있습니다.

예를 들어 zsh 또는 yash에서는 다음과 같습니다.

slice=${string[1,4]}${string[14,17]}${string[-4,-1]}

zsh에서는 다음과 같이 단축할 수 있습니다.

slice=$string[1,4]$string[14,17]$string[-6,-1]

일부 부품을 제자리에서 잘라낼 수 있습니다.

$ string[5,13]= string[9,-7]=
$ print -r -- $string
SHOWTHISSTRING

또는 최신 버전의 ksh93, 또는 다음 bash을 사용하세요 .zshmksh

slice=${string:0:4}${string:13:4}${string: -6}

POSIX적으로:

tmp=${string#?????????????}
slice=${string%"${string#????}"}${tmp%"${tmp#????}"}${string#"${string%????}"}

그럼에도 불구하고권장될 수도 있습니다. 이 옵션은 의 일관성을 유지하기 위해 -c일부 구현에 추가되었으며 문자가 여러 바이트로 구성될 수 있다는 개념이 나오기 훨씬 전에 추가되었습니다 .head-ctail-ctail

답변2

headtail해당 옵션을 지원한다고 가정하면 -c문자열은 멀티바이트 문자가 없는 단순한 ASCII에 지나지 않으며 쉘은 <<<여기에서 문자열 구성을 지원합니다(bash 및 zsh 모두 지원). 다음을 수행할 수 있습니다.

$ string=SHOWpijfirefjTHISezpijSTRING
$ printf '%s%s%s\n' "$(head -c 4 <<<"$string")" \
                    "$(head -c 17 <<<"$string" | tail -c 4)" \
                    "$( tail -c 5 <<<"$string")"
SHOWTHISRING

또는 원하지 않는 경우 printf:

$ string=SHOWpijfirefjTHISezpijSTRING
$ head -c 4 <<<"$string"; \
  head -c 17 <<<"$string" | tail -c 4; \
  tail -c 5 <<<"$string"; 
SHOWTHISRING

관련 정보