25k 문자열을 부분적으로 진행하는 가장 좋은 방법은 무엇입니까?

25k 문자열을 부분적으로 진행하는 가장 좋은 방법은 무엇입니까?

25,000개의 문자가 있습니다.

printf나는 임의의 수의 문자를 순서대로 인쇄하는 스크립트를 작성하고 싶습니다 .

설명하다:

주문 번호

어디숫자1-25000 사이의 값이 될 수 있으며 이 출력을 얻을 수 있습니다.

나는 데이터를 별도의 파일에 저장하고 싶지 않으며(가장 쉬운 솔루션?) POSIX 쉘 명령을 사용하는 것을 선호합니다(스크립트를 가능한 한 이식 가능하게 만들기 위해: awk 또는 Perl이 이것을 간단하게 해킹할 수 있다는 것을 알고 있습니다). .

이 데이터를 변수에 저장해야 합니까? 아니면 명령( )을 printf통해 전체 프로그램을 실행하시겠습니까 ? 아니면 또 다른 (더 나은?) 해결책이 있나요? 왜 다른 옵션보다 하나의 옵션을 선택해야 합니까?cutcut -c -$1

내가 간과한 다른 문제/경고는 무엇입니까?

답변1

dd순서를 생각해 보셨나요? 이를 통해 원하는 만큼의 바이트를 건너뛴 다음 원하는 만큼의 바이트를 출력할 수 있습니다.

dd if=infilename bs=1 skip=sk count=ct 2>/dev/null

dd, 파일 이름 입력, 블록 크기 1, 먼저 건너뛰기SK파일의 바이트를 입력하고 복사하십시오.CT바이트를 표준 출력으로 보냅니다(또는 지정된 파일을 사용합니다 of=name). 일반적으로 끝에 인쇄되는 상태 메시지를 방지하려면 오류 메시지를 리디렉션하세요.

답변2

이식성과 신뢰성을 고려하여 빅데이터를 변수로 저장하는 것은 좋은 생각이 아닐 수 있습니다. awk이식하기 쉬운 비 POSIX 솔루션의 경우 sed.

설명하다

데이터 양이 많은 경우 변수로 저장하지 마세요. 하지만Bash 자체에는 제한이 없지만 운영 체제에서는 제한이 있을 수 있습니다.

"내 운영 체제에서 작동합니다"라고 가정해 보겠습니다. 하지만,

  • 운영 체제마다 제한 사항이 다릅니다.
  • 따라서 이식성을 최대화하고 싶다면 왜 스크립트가 한 운영 체제에서 실행되고 다른 운영 체제에서 충돌할 위험을 감수해야 합니까?
  • 따라서 처음에 변수에 저장하지 않음으로써 이 문제를 피하십시오.

그런 다음 파일에 저장합니다. 특히 문자열을 문자(또는 원하는 가장 작은 단위)와 별도의 줄로 나눕니다.

그런 다음 다음을 사용하십시오 sed.

  • sed는 전체 대용량 파일을 로드할 필요가 없으며 한 줄씩 작동합니다.
  • sedPOSIX 사양에 정의됨, 귀하의 요구 사항을 충족 non-AWK하지만 여전히 POSIX입니다.

또한 파일 사용의 코드 유지 관리 이점을 고려하십시오. 스크립트에서 코드를 탐색하는 것보다 파일에 저장된 줄을 업데이트하는 것이 더 쉬울 수 있습니다.

파일에 한 줄에 한 문자(또는 "단계별"하려는 가장 작은 단위)의 데이터가 있습니다 data.lst.

a
b
c
d
e

다음을 포함할 수 있습니다 script.sh.

#!/bin/bash

stop_number="$1"

sed -n "1,${stop_number}p" data.lst

따라서 명령 프롬프트에서 테스트하고 다음을 확인하세요.

$ ./script.sh 3
a
b
c
  • 에서 지정한 수만큼 라인을 sed인쇄 하는 데 사용됩니다 . 명확성을 위해 직접적으로 작성하는 대신1$stop_number$stop_number$1
  • $stop_number물론, $1입력하려는 임의의 숫자인 위치 매개변수 를 통해 얻습니다.
  • data.lst따라서 나타나는 순서대로 3개의 문자를 성공적으로 따릅니다 .data.lst
  • 이때 실제 행 수보다 큰 숫자를 입력하면 모든 행만 표시됩니다.
  • 현재는 data.lst같은 디렉토리에 있지만 script.sh원하지 않는 경우 실제로 다른 곳에 있는 경우 ~/some/dir/data.lst다음과 같이 조정하면 됩니다 .~/some/dir/data.lst

따라서 실제 데이터가 있으면 data.lst이 스크립트를 직접 테스트할 수 있습니다.

답변3

Tom에게서 조금 빌리려면:

#!/bin/sh
skp(){  dd bs="$1" skip=1 count=0; }    # direct seek to target
rd (){  dd bs="$1" skip=0 count=1; }    # single read at target
tail=$(sed -ne'/^don/{=;q;}' <"$0")     # skip script by line#
while   [ 1 -gt "$#" ] && exit          # exit when args exhausted
        exec <&- <"$0" || exit          # exec <"$0" each iteration
do      head -n "$tail" >&3             # only consider the tail
        case ${2+$1}  in                # test args
        (*[1-9]*|-*[!0]*)               # skp() when ${2++} && $1 != 0
          skp "$1";esac 2>&3            # send stderr to dev/null
          rd  "${2-$1}" 2>&3            # else just rd() from head of offset
        echo; shift ${2+"2"}            # append a newline and shift args away
done    3>/dev/null                     # put your data below this

변수에 넣지 말고 파일에 넣으십시오. 25k 변수는 쉘이 처리하기에 재미가 없으며 파일이추구싱글에서는,거의원자적 행동. 따라서 바이트 23843 - 24843을 인쇄하려면 위와 같은 작업을 수행한 후 다음을 사용하여 호출할 수 있습니다.

myscript 23843 1000

...먼저 a는 head파일 설명자의 공유 표준에서 스크립트의 모든 줄을 제거하여 오프셋이 문자열 머리 부분에서 정확히 25k로 설정되도록 합니다. 그런 다음 첫 번째 줄 dd찾다오프셋은 ~23k이고 두 번째 오프셋은 dd이를 읽습니다. 이것이 가장 간단한 방법입니다. 쉘은 문자별로 읽도록 설계되었습니다. read예를 들어 일반적인 쉘의 내장 기능은 다음을 수행합니다.1바이트 read()개행 문자가 발견될 때까지 반복하고 개행 문자가 발견될 때까지 멈추지 마십시오. 각 매개변수 쌍에 대해 하나의 작업이 dd수행됩니다 .read

이것이 제가 테스트한 방법입니다:

# after a copy to my clipboard
ddscr(){ sh /tmp/ddscr.sh "$@"; }
{ xsel; man man; } > /tmp/ddscr.sh
{ echo show the size; ls -l /tmp/ddscr*
  echo read from the top; ddscr 80
  echo from the middle;   ddscr 15k 160
  echo from the tail;     ddscr 64k | tail -n5
}

show the size
-rw-r--r-- 1 mikeserv mikeserv 37564 Dec 13 11:27 /tmp/ddscr.sh
read from the top
MAN(1)                           Manual pager utils                          MAN
from the middle
lso use manconv(1) directly.
              However, this option allows you to convert several manual pages to  a
              single  encoding  without  having
from the tail
       31st  March  2001  -  present day: Colin Watson <[email protected]> is now
       developing and maintaining man-db.

2.7.5                                2015-11-06                              MAN(1)

...그리고...

ddscr 10k 10 20k 10 10250 10

       fi
is  option
le.   If

답변4

프로그램과 데이터를 동일한 파일로 감싸고 싶다면 가장 좋은 방법은 perl. ); Windows에서는 표준으로 찾을 수 없지만 Windows에서도 찾을 수 없습니다 bash.

#!/usr/bin/env perl
print substr(<DATA>, $ARGV[0], $ARGV[1]), "\n";

__DATA__
Just add all your text after 
the __DATA__ line... no fuss, no quoting, 
no tricks

예를 들어, 이름을 selected_print로 지정하고 10부터 시작하여 30자를 인쇄한다고 가정해 보겠습니다.

% selective_print 10 30

관련 정보