인터넷 검색을 해봤지만 while 루프를 사용하여 줄을 읽는 스크립트를 찾을 수 없습니다. 막혔고 어디서부터 시작해야 할지 모르겠어요
문제는 다음과 같습니다. 표준 입력에서 텍스트 행을 읽기 위해 while 읽기 루프를 사용하는 bash 스크립트 Longline.sh를 작성하십시오. 스크립트는 지금까지 읽은 가장 긴 줄을 추적하고 입력 끝에 도달하면 해당 줄을 인쇄해야 합니다.
또한 질문에서 텍스트 줄이 포함된 파일을 입력하라는 메시지가 표시되면 해당 파일을 읽거나 텍스트 줄 자체를 입력할지 확실하지 않습니다.
감사합니다.KB
답변1
cuonglm의 링크에 따르면 bash
루프는 피해야 합니다.
awk
이러한 의미에서 다음 코드는 표준 Unix 도구를 사용하여 파일에서 가장 긴 줄의 길이를 가져오지만 bash
반복은 하지 않습니다.
awk '{n=length($0)>n?length($0):n} END{print n}' file
길이를 얻는 대신 가장 긴 줄을 인쇄하려면 다음을 사용하십시오.
awk '{longest=length($0)>length(longest)?$0:longest} END{print longest}'
답변2
나는 오랫동안 bash로 글을 쓰지 않았기 때문에 어떤 비판이라도 받아들일 것입니다. :) 내 해결책은 다음과 같습니다.
n=0
longest=""
while read line; do
len=`echo $line | wc -m`
if [ $len -ge $n ]; then
n=$len
longest=$line
fi
done
echo $longest
@cuonglm의 제안을 읽었지만 더 적은 수의 프로세스 호출로 이를 수행할 수 있는 방법이 생각나지 않습니다. 물론, 나는 제안에 열려있습니다.
마지막 질문에 관해서는 실제로 중요하지 않습니다. 스크립트는 사용자가 입력하는 줄이나 입력으로 사용되는 파일에 대해 작업할 수 있습니다.
답변3
한 줄에 하나씩 모든 줄 번호 목록을 얻을 수 있습니다. 첫 번째는 길이별로 정렬되고 두 번째는 가장 큰 것부터 시작하여 줄 번호별로 정렬됩니다.
</path/to/infile LC_ALL=C \
tr -c \\n 1|grep -n '.\|'|sort -t: -rnk2
방법은 매우 간단합니다. ewline 문자가 아닌 tr
모든 입력 바이트를 1로 변환하고 입력의 모든 행 앞에 각 행의 번호를 추가한 다음 입력에 a를 추가한 다음 역순으로 2cd부터 시작합니다. 필드가 정렬됩니다. a로 구분된 줄의 끝까지. 따라서 가장 긴 문자열이 맨 위로 떠오릅니다.\n
grep -n
:
sort
:
그러나 입력에 멀티바이트 문자가 포함되어 있으면 문자가 아닌 바이트로만 번호가 매겨진다는 점에 유의해야 합니다. 후자를 잘하는 것은 작은 문제가 아니다.(내가 아는 한).
그럼에도 불구하고 - ASCII 로케일에서 - 위의 내용은 매우 큰 입력의 경우에도 매우 빠릅니다. 완전한 솔루션이 되기 위해서는 다른 것이 거의 필요하지 않습니다.
f=/path/to/file
n=$(<"$f" tr -c \\n 1|grep -n '.\|'|sort -t: -rnk2|head -n1)
l=$(<"$f" head -n"${n%:*}"|tail -n1)
printf "Line #%s at #${#l} bytes. Its contents:\n%s\n" \
"${n%:*} is (possibly tied-for) the longest in $f" "$l"