업데이트(행의 20% 가져오기):

업데이트(행의 20% 가져오기):

예를 들어 N개의 파일(file1, file2, file3...)이 있습니다.

그 중 처음 20%가 필요하며, 결과 디렉터리는 (file1_20, file2_20, file3_20...)과 같아야 합니다.

wc이것을 사용하여 파일의 줄 수를 구한 다음 0.2를 곱하고 싶습니다 .

그런 다음 get 20%를 사용한 head다음 새 파일로 리디렉션하지만 자동화하는 방법을 모르겠습니다.

답변1

따라서 작동하는 예제를 작성하십시오.

root@crunchbang-ibm3:~# echo {0..100} > file1        
root@crunchbang-ibm3:~# cat file1
    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

다음 명령을 사용하여 파일 크기를 바이트 단위로 얻을 수 있습니다 stat.

root@crunchbang-ibm3:~# stat --printf %s "file1"
294

그런 다음 다음을 사용하여 bc크기에 0.2를 곱할 수 있습니다.

root@crunchbang-ibm3:~# echo "294*.2" | bc
58.8

그러나 부동 소수점을 얻었으므로 이를 정수로 변환해 보겠습니다 head( dd이 방법도 작동합니다).

root@crunchbang-ibm3:~# printf %.0f "58.8" 
59

마지막으로 file1의 처음 20%(바이트 제공 또는 가져오기):

root@crunchbang-ibm3:~# head -c "59" "file1" 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

그것들을 합치면 다음과 같은 일을 할 수 있습니다

mkdir -p a_new_directory
for f in file*; do
    file_size=$(stat --printf %s "$f")
    percent_size_as_float=$(echo "$file_size*.2" | bc)
    float_to_int=$(printf %.0f "$percent_size_as_float")
    grab_twenty=$(head -c "$float_to_int" "$f")
    new_fn=$(printf "%s_20" "$f") # new name file1_20
    printf "$grab_twenty" > a_new_directory/$new_fn
done

ffor 루프가 실행되는 디렉터리에서 발견된 항목에 대한 자리 표시자는 어디에 있습니까?file*

마친 후:

root@crunchbang-ibm3:~# cat a_new_directory/file1_20
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 

업데이트(행의 20% 가져오기):

행의 처음 20% 정도를 얻으려면 다음 stat --printf %s "$f"으로 바꿀 수 있습니다.

wc -l < "$f"

를 사용하고 있으므로 printf효과적으로 bcfrom 을 반올림할 수 있지만 .5파일 길이가 1~2줄에 불과하면 누락됩니다. 따라서 반올림해야 할 뿐만 아니라 기본적으로 최소한 1개의 행을 가져와야 합니다.

답변2

댕댕. 나는 아카이브를 구문 분석하는 복잡한 방법을 사용하여 전체 답변을 작성했습니다 tar. 이는 매우 멋진 일입니다. 하지만 결국 나는 이 중 어느 것도 필요하지 않다는 것을 깨달았습니다. 필요한 것은 sed약간의 쉘 수학입니다.

set ./file[1-5];i=1 n=;eval "${n:=
}       sed -n  \"$(grep -c '.\|' "$@"|
        sed 's|\(.*\):\(.*\)|\
        $i,$(((\2/5)+(i+=\2)-\2))w \1|
        ')\" <<!$n"'$(cat "$@")'"$n!$n"

어떤 파일에서든 grep -c줄 수를 와일드카드로 지정하고(나는 와일드카드로 file[1-5]) 개수를 지정한 sed다음, 쉘의 약간의 도움을 받아 자신만의 스크립트를 작성합니다. cat여기 문서를 통해 입력을 제공하세요. 이는 파일을 읽으려고 하는 동안 sed파일 중 하나를 열고 쓰기 시작 하면 어떤 일이 일어날지 확신할 수 없기 때문입니다 cat. 그리고 크기에 따라 파이프보다 버퍼를 처리하는 것이 조금 더 나을 것이라고 생각합니다. 하지만 나는 그것에 대해 너무 명확하지 않습니다.

이를 통해 단일 스트림의 모든 파일을 읽고 w이에 따라 출력을 작성할 수 있습니다. 파일 번호를 적절하게 늘리려면 몇 가지 설정이 필요하므로 두려워할 필요가 없습니다 grep. 다음은 수행 중인 작업을 보여주는 eval몇 가지 출력입니다 .set -x

+ set ./file1 ./file2 ./file3 ./file4 ./file5
+ i=1 n=
+ + grep -c .\| ./file1 ./file2 ./file3 ./file4 ./file5
        sed s|\(.*\):\(.*\)|\
        $i,$(((\2/5)+(i+=\2)-\2))w \1|

+ eval 
       sed -n  "
        $i,$(((18400/5)+(i+=18400)-18400))w ./file1

        $i,$(((18411/5)+(i+=18411)-18411))w ./file2

        $i,$(((18415/5)+(i+=18415)-18415))w ./file3

        $i,$(((18418/5)+(i+=18418)-18418))w ./file4

        $i,$(((18421/5)+(i+=18421)-18421))w ./file5" <<!
$(cat "$@")
!

+ cat ./file1 ./file2 ./file3 ./file4 ./file5
+ sed -n 
        1,3681w ./file1

        18401,22083w ./file2

        36812,40495w ./file3

        55227,58910w ./file4

        73645,77329w ./file5

보시다시피, 행은 스트림의 각 파일 위치에 따라 주소가 지정되고 w해당 파일 이름을 읽을 때 작성됩니다. 그러나 중요한 점은 경로 이름에서 이식할 수 없는 문자를 처리하려고 시도하지 않는다는 것입니다. 특히 이 경우 sed write 명령이 줄 바꿈에서 파일 이름 인수를 구분하기 때문에 경로 이름에 새 줄을 사용할 수 없습니다. 필요한 경우 ln필요한 경우 이 상황을 쉽게 해결할 수 있습니다.

wsed또한 단일 스크립트 내에서 지원될 수 있는 rite 파일 설명자 수에는 제한이 있다는 점을 언급하고 싶습니다 . 이것사양에 따르면:

[ sed필수]w많은 구현의 역사적 관행과 일치하는 최소 10개의 서로 다른 파일이 지원됩니다. 추가이지만 규정을 준수하는 애플리케이션을 지원하도록 구현하는 것이 좋습니다.초과해서는 안 된다이 제한.

따라서 위에 작성된 명령은 최대 10개의 동시 읽기/쓰기 파일을 지원하여 모든 POSIX 시스템으로 이식 가능해야 합니다. 이러한 종류의 내용이 더 많은 콘텐츠가 필요할 수 있는 게시된 스크립트나 애플리케이션에 통합된 경우 다음과 같이 미리 처리됩니다 /tmp.

: & set '"" "" "" "" "" "" "" "" "" "" ';n='
' f=/tmp/$$$!'_$((i+=1))' MAXw=[num]
while eval "set '$1$1' $1;exec <<!$n\$(((i=0)+\$#))$n!$n 
      i=\$(sed \"$(IFS=\ ;printf "\nw $f%.0s" $1)\")"
      [ "$(($#==i?(_i=i-1):(MAXw=_i)))" -lt "$MAXw" ]
do :;done; rm "/tmp/$$$!"*; unset _i i f n

sed...이것은 현장에서 상당히 이식 가능한 역량 측정 기준이어야 합니다 . GNU는 약 1초 만에 sed4093개의 동시에 열린 파일에서 멈춥니다 w. 하지만 이는 아마도 내 시스템의 최대값일 것이며 영향을 받을 수도 있습니다 ulimit. 완료되면 $i시도할 때마다 doubles 값이 확인되므로 2560과 5120 $_i에 남습니다 . $i루프가 닫힐 때 위의 더 안전한 값을 기본적 $MAXw으로 사용합니다. 주로 파일을 열 수 없는 경우 모든 s가 반환 값을 올바르게 설정할지 확신할 수 없기 때문입니다 . 하지만 독자는 이를 사용하여 원하는 작업을 수행할 수 있습니다.$_isedw

의 초기 [num]값 은 $MAXw실제 숫자(원하는 최대 w파일 수가 무엇이든)이어야 하며 리터럴 숫자가 아니어야 합니다 [num].

여기에 있는 문서화에 관해 다시 한 번 말씀드리지만, 제 생각에는 이 경우에는 그와 유사한 것이 좋은 생각입니다. sed읽는 동안 쓰기 설명자가 유지되어야 하므로 동일한 입력/출력 이름으로 무엇을 할 수 있는지는 알 수 없습니다. 그러나 쉽게 사용할 수 있는 대안이 있는 경우에는 취할 가치가 있는 기회가 아니라고 생각합니다.

내 테스트 파일은 다음과 같이 생성됩니다.

for n in 1 2 3 4 5
do : & seq -s "$(printf "%015s--$n--%015s\n\t")" "$!" >"file$n"
done

...폐기된 프로세스 PID의 커널에서 상당히 연속적인 의사 난수를 얻습니다. 파일 내용은 분할의 불일치를 나타내도록 의도적으로 설계되었습니다. 샘플 세트의 전후 모습은 다음과 같습니다.

앞으로:

for f in file[1-5]; do
nl -ba "$f" | sed -n '$p;$=;1,3p
'; done

     1  1               --1--             
     2          2               --1--     
     3          3               --1--     
  3681          3681               --1--  
3681
     1  1               --2--             
     2          2               --2--     
     3          3               --2--     
  3683          3683               --2--  
3683
     1  1               --3--             
     2          2               --3--     
     3          3               --3--     
  3684          3684               --3--  
3684
     1  1               --4--             
     2          2               --4--     
     3          3               --4--     
  3684          3684               --4--  
3684
     1  1               --5--             
     2          2               --5--     
     3          3               --5--     
  3685          3685               --5--  
3685

형식이 조금 이상해 보인다면 첫 번째 출력 행 앞에 구분 기호 문자열이 삽입 seq되지 않았기 때문일 수 있습니다. -s중요한 것은 sed모두 seqnl줄 번호에 동의하는 것 같습니다. 그래도...

뒤쪽에: ...

  sed -n 
  1,737w ./file1

  3682,4418w ./file2

  7365,8101w ./file3

  11049,11785w ./file4

  14733,15470w ./file5
  ...
     1  1               --1--           
     2          2               --1--   
     3          3               --1--   
   737          737               --1-- 
737
     1  1               --2--           
     2          2               --2--   
     3          3               --2--   
   737          737               --2-- 
737
     1  1               --3--           
     2          2               --3--   
     3          3               --3--   
   737          737               --3-- 
737
     1  1               --4--           
     2          2               --4--   
     3          3               --4--   
   737          737               --4-- 
737
     1  1               --5--           
     2          2               --5--   
     3          3               --5--   
   738          738               --5-- 
738

그게 바로 간단하고 효율적인 스트리밍입니다.

답변3

언급한 도구를 사용하십시오. + find: 또는을 사용하여 라인 또는 바이트 1
의 백분율을 얻으십시오. 여기서는 또는에 의해 제공되며 마지막으로 해당 에 출력을 씁니다. head -n perc filehead -c perc file
perc(( count / 5 ))
countwc -l < filewc -c < file
file_20

참고: /연산자는 가장 가까운 정수로 반올림하므로 file*행/바이트 count < 5(so perc = 0)가 있는 모든 파일은 빈 파일을 생성합니다 file*_20.

상위 20% 가져오기 - 행:

mkdir some_dir_name
find . -maxdepth 1 -iname 'file*' -exec sh -c 'head -n $(( $(wc -l < "$0") / 5 )) "$0" > some_dir_name/"$0"_20' {} \;

처음 20%를 가져옵니다 - 바이트:

mkdir some_dir_name
find . -maxdepth 1 -iname 'file*' -exec sh -c 'head -c $(( $(wc -c < "$0") / 5 )) "$0" > some_dir_name/"$0"_20' {} \;


1텍스트 레이아웃에 따라 두 가지 방법은 예를 들어 10줄의 텍스트 예에서 상당히 다른 결과를 생성할 수 있습니다 .

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.


Abstract

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat. 

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum...

총 행의 처음 20% = 처음 2개 행:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.

총 바이트의 처음 20% = 첫 번째 줄(잘림):

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do

관련 정보