태그 보관물: awk

awk

파일에서 가장 긴 줄을 인쇄하는 방법? 인터넷 검색을했는데 놀랍게도 대답을

파일에서 가장 긴 줄을 인쇄하는 가장 간단한 방법을 찾고 있습니다. 나는 인터넷 검색을했는데 놀랍게도 대답을 찾지 못하는 것 같습니다. 파일에서 가장 긴 줄의 길이를 자주 인쇄하지만 실제로 가장 긴 줄을 인쇄하는 방법을 모르겠습니다. 누구든지 파일에서 가장 긴 줄을 인쇄하는 솔루션을 제공 할 수 있습니까? 미리 감사드립니다.



답변

cat ./text | awk ' { if ( length > x ) { x = length; y = $0 } }END{ print y }'

UPD : 의견에 모든 조언을 요약

awk 'length > max_length { max_length = length; longest_line = $0 } END { print longest_line }' ./text 


답변

cat filename | awk '{ print length }' | sort -n | tail -1


답변

sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file

먼저 명령 대체 내부의 파일을 읽고 가장 긴 줄의 길이를 출력합니다 (이전 expand의 의미를 극복하기 위해 탭을 공백으로 변환 함 wc -L-줄의 각 탭 은 1 에서 줄 길이 대신 8 을 추가합니다 ). 그런 다음이 길이는 sed“이 문자 수만큼 줄을 찾아서 인쇄 한 다음 종료”를 의미 하는 표현식에 사용됩니다 . 따라서 이것은 가장 긴 줄이 파일의 상단에 가까울수록 최적 일 수 있습니다.

다른 하나는 sed보다 먼저 생각했습니다 (bash).

#!/bin/bash
while read -r line; do
    (( ${#line} > max )) && max=${#line} && longest="$line"
done
echo "$longest"


답변

Perl 솔루션은 다음과 같습니다.

perl -e 'while(<>){
           $l=length;  
           $l>$m && do {$c=$_; $m=$l}  
         } print $c' file.txt 

또는 가장 긴 줄을 모두 인쇄 하려면

perl -e 'while(<>){
           $l=length;
           push @{$k{$l}},$_;
           $m=$l if $l>$m;
         } print @{$k{$m}}' file.txt 

더 나은 작업이 없었기 때문에 625M 텍스트 파일에서 일부 벤치 마크를 실행했습니다. 놀랍게도 내 Perl 솔루션은 다른 솔루션보다 지속적으로 빠릅니다. 물론 허용되는 awk솔루션 과의 차이 는 작지만 존재합니다. 분명히 여러 줄을 인쇄하는 솔루션은 느리므로 유형별로 정렬하여 가장 빠르거나 느립니다.

가장 긴 줄 중 하나만 인쇄하십시오.

$ time perl -e 'while(<>){
           $l=length;  
           $l>$m && do {$c=$_; $m=$l}  
         } print $c' file.txt 
real    0m3.837s
user    0m3.724s
sys     0m0.096s



$ time awk 'length > max_length { max_length = length; longest_line = $0 }
 END { print longest_line }' file.txt
real    0m5.835s
user    0m5.604s
sys     0m0.204s



$ time sed -rn "/.{$(<file.txt expand -t1 |wc -L)}/{p;q}" file.txt 
real    2m37.348s
user    2m39.990s
sys     0m1.868s

가장 긴 줄을 모두 인쇄하십시오.

$ time perl -e 'while(<>){
           $l=length;
           push @{$k{$l}},$_;
           $m=$l if $l>$m;
         } print @{$k{$m}}' file.txt 
real    0m9.263s
user    0m8.417s
sys     0m0.760s


$ time awk 'length >x { delete y; x=length }
     length==x { y[NR]=$0 } END{ for (z in y) print y[z] }' file.txt
real    0m10.220s
user    0m9.925s
sys     0m0.252s


## This is Chris Down's bash solution
$ time ./a.sh < file.txt 
Max line length: 254
Lines matched with that length: 2
real    8m36.975s
user    8m17.495s
sys     0m17.153s


답변

가장 긴 줄을 잡으십시오

grep -Em1 "^.{$(wc -L <file.txt)}\$" file.txt 

이 명령은 쉘 구문과 regexp 구문을 혼합하기 때문에 연습 없이는 읽기가 매우 어렵습니다.
설명을 위해 먼저 단순화 된 의사 코드를 사용합니다. 로 시작하는 행 ##은 쉘에서 실행되지 않습니다.
이 단순화 된 코드는 파일 이름 F를 사용하고 가독성을 위해 인용 부호와 정규 표현식의 일부를 생략합니다.

작동 원리

이 명령에는 grep-와 wc호출의 두 부분이 있습니다 .

## grep "^.{$( wc -L F )}$" F

wc프로세스 확장에 사용되는, $( ... )그래서 그것은 전에 실행됩니다 grep. 가장 긴 줄의 길이를 계산합니다. 쉘 확장 구문은 혼란스러운 방식으로 정규식 패턴 구문과 혼합되므로 프로세스 확장을 분해합니다.

## wc -L F
42
## grep "^.{42}$" F

여기서 프로세스 확장은 반환 된 값으로 바뀌어 grep사용되는 명령 줄을 만듭니다 . 이제 정규식을보다 쉽게 ​​읽을 수 있습니다 . 줄의 시작 ( ^)에서 끝 ( $) 까지 정확히 일치합니다 . 그 사이의 표현은 개행을 제외한 모든 문자와 일치하며 42 번 반복됩니다. 즉, 정확히 42 자로 구성된 행입니다.

이제 실제 쉘 명령으로 돌아갑니다. grep옵션 -E( --extended-regexp)을 사용하면 {}가독성을 피할 수 없습니다 . 옵션 -m 1( --max-count=1)은 첫 번째 줄을 찾은 후에 중지합니다. <wc명령을 방지하기 위해, 표준 입력에 파일을 기록 wc길이와 함께 파일 이름을 인쇄에서.

가장 긴 줄은?

두 번 나타나는 파일 이름으로 예제를 더 읽기 쉽게하기 위해 파일 이름에 변수 f를 사용합니다 . $f예제에서 각각 은 파일 이름으로 대체 될 수 있습니다.

f="file.txt"

첫 번째 가장 긴 줄가장 긴 줄 만큼 긴 첫 번째 줄을 표시하십시오 .

grep -E -m1 "^.{$(wc -L <"$f")}\$" "$f"

보기 모두 긴 줄 – 긴 긴 라인 등으로 모든 라인을 :

grep -E "^.{$(wc -L <"$f")}\$" "$f" 

마지막으로 긴 줄 – 긴 줄만큼 긴 마지막 줄을 :

tac "$f" | grep -E -m1 "^.{$(wc -L <"$f")}\$"

하나의 가장 긴 줄 -다른 모든 줄보다 가장 긴 줄을 표시 하거나 실패하십시오.

[ $(grep -E "^.{$(wc -L <"$f")}\$" "$f" | wc -l) = 1 ] && grep -E "^.{$(wc -L <"$f")}\$" "$f" 

(마지막 명령은 완전한 grep 명령을 반복하므로 다른 명령보다 훨씬 비효율적입니다. 출력 wc과 행이 쓴 행 grep이 변수에 저장 되도록 분명히 분해해야 합니다.
가장 긴 행은 실제로 모든 행일 수 있습니다. 변수로 저장하려면 처음 두 줄만 유지하면됩니다.)


답변

다음 예제는 dmitry.malikov의 답변에 대한 주석이 되었을 것입니다. 그러나 보이지 않는 주석 공간쓸모없는 사용으로 인해 여기서 볼 수있는 곳을 제시했습니다. ..

이것은 드미트리의
단일 패스 awk 방법 간단한 변형입니다 .
모든 “동일한 가장 긴”줄을 인쇄합니다. (참고. delete arraygawk 확장명입니다).

awk 'length >x { delete y; x=length }
     length==x { y[NR]=$0 } END{ for (z in y) print y[z] }' file


답변

순수한 배쉬에서 :

#!/bin/bash

_max_length=0
while IFS= read -r _line; do
    _length="${#_line}"
    if (( _length > _max_length )); then
        _max_length=${_length}
        _max_line=( "${_line}" )
    elif (( _length == _max_length )); then
        _max_line+=( "${_line}" )
    fi
done

printf 'Max line length: %d\n' "${_max_length}"
printf 'Lines matched with that length: %d\n' "${#_max_line[@]}"
(( ${#_max_line[@]} )) && printf '%s\n' '----------------' "${_max_line[@]}"