안녕하세요. 헤드, 테일, 파이프(결국 리디렉션)만 사용하여 문자열의 시작, 중간, 끝을 추출하고 출력하는 방법이 있는지 궁금합니다.
예: 다음 문자열이 주어지면 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
}
head
GNU 의 head
내장 함수 에서는 작동 ksh93
하지만 head
busybox에서는 작동하지 않는 방법을 확인하세요 . 을 실행하면 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 대신 바이트 head
가 tail
사용되므로 -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
을 사용하세요 .zsh
mksh
slice=${string:0:4}${string:13:4}${string: -6}
POSIX적으로:
tmp=${string#?????????????}
slice=${string%"${string#????}"}${tmp%"${tmp#????}"}${string#"${string%????}"}
그럼에도 불구하고씨권장될 수도 있습니다. 이 옵션은 의 일관성을 유지하기 위해 -c
일부 구현에 추가되었으며 문자가 여러 바이트로 구성될 수 있다는 개념이 나오기 훨씬 전에 추가되었습니다 .head
-c
tail
-c
tail
답변2
head
및 tail
해당 옵션을 지원한다고 가정하면 -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