file.log.1
덮어쓴 로그 파일( 등 ) 이 많이 있습니다 file.log.2
. 장치에서 로컬 컴퓨터로 복사할 때 원래 타임스탬프가 손실되었습니다. 그래서 시간순으로 정리하고 싶습니다. 문제는 무엇이 최신이고 무엇이 가장 오래된 것인지 반드시 알 수 없다는 것입니다.
내가 원하는 것은 모든 로그가 하나의 디렉토리에 있는 경우 다음과 같이 인쇄하는 것입니다.
file: file.log.1
first line: [first line that isn't whitespace]
last line: [last line that isn't whitespace]
이를 위해 Python 스크립트를 작성할 수 있지만 가능하다면 Linux 내장 스크립트를 사용하는 것이 좋습니다. awk/sed를 위한 작업인가요? 아니면 이것이 실제로 스크립팅 언어에 더 적합합니까? 대답이 '예'라면 awk/sed는 무엇을 합니까?
검색을 통해 이 awk 명령을 찾았지만 파일 이름만 허용하고 마지막 줄의 내용을 인쇄합니다(그리고 끝에는 가변 개수의 빈 줄이 있을 수 있습니다).
awk 'NR == 1 { print }END{ print }' filename
답변1
그래서 나는 sed
이 대답을 좋아한다.
for file in file.log.*
do
echo "file: $file"
echo -n "first line: "
cat "$file" | sed -n '/^\s*$/!{p;q}'
echo -n "last line: "
tac "$file" | sed -n '/^\s*$/!{p;q}'
done
답변2
awk 명령:
awk -v OFS=: '
FNR==1 {
# the last non-blank line from the previous file
if (line) {print filename, fnr, line}
filename=FILENAME
line=""
p=0
}
/^[[:blank:]]*$/ {next}
!p {
# the first non-blank line
print FILENAME, FNR, $0; p=1
}
{fnr=FNR; line=$0}
END {print filename, fnr, line}
' *
각 파일에 대해 파일 이름, 줄 번호, 줄을 콜론으로 구분하여 인쇄합니다.
GNU awk v4에는 BEGINFILE 및 ENDFILE 모드가 있어 작업이 크게 단순화됩니다.
gawk -v OFS=: '
BEGINFILE {p=0}
/^[[:blank:]]*$/ {next}
!p {print FILENAME, FNR, $0; p=1}
{fnr=FNR; line=$0}
ENDFILE {print FILENAME, fnr, line}
' *
답변3
노력하다:
awk -F'\n' -vRS="" '
{
print "file: " FILENAME;
gsub(/\n[[:blank:]]+|[[:blank:]]+\n/,"");
print "first line: " $1;
print "last line: " $NF;
}
' file.log.*
답변4
무엇? 펄은 없나요?
for file in file.log.*; do
echo "FILE: $file";
perl -ne 'if(/\S/){$k++; $l=$_};
print "First line: $_" if $k==1;
END{print "Last line: $l\n"}' "$file";
done
설명하다
for file in file.log.*
file.log.
: 현재 디렉터리에서 이름이 로 시작하는 모든 파일을 반복하고 각 파일을$file
.echo "FILE: $file";
: 파일 이름을 인쇄합니다.perl -ne
: 현재 입력 파일을 한 줄씩 읽고(-n
) 각 줄을 특수 Perl 변수로 저장한 다음$_
해당 파일에서 주어진 스크립트를 실행합니다.-e
if(/\S/){$k++; $l=$_}
: 현재 줄이 공백이 아닌 문자(\S
)와 일치하는 경우 줄을 다른 이름으로 저장$l
하고 카운터를$k
1씩 증가시킵니다.print "First line: $_" if $k==1;
: 그렇다면 현재 행($_
)을 인쇄합니다. 그러면 비어 있지 않은 첫 번째 줄이 인쇄됩니다.$k
1
END{print "Last line: $l\n"}
: 입력 라인을 모두 읽은 후 실행합니다. 비어 있지 않은 모든 줄을 로 저장하므로$l
파일 끝에는$l
비어 있지 않은 마지막 줄이 있습니다. 그러면 마지막 줄이 인쇄됩니다.
또 다른 방법:
for file in file.log.*; do
printf "FILE: %s\nFirst line: %s\nLast line: %s\n\n" \
"$file" \
"$(grep -Em 1 '\S' "$file")" \
"$(tac "$file" | grep -Em1 '\S' )";
done
설명하다
이것은 세 개의 문자열을 인쇄하기 for
위해 여기서 사용한 것과 동일한 루프입니다 printf
. 파일 이름과 다음 두 명령의 출력은 다음과 같습니다.
grep -Pm 1 '\S' "$file"
:-E
확장된 정규식을 활성화하여\S
"공백 없음"을 사용할 수 있도록 합니다.-m1
"첫 번째 일치 항목을 찾은 후 종료"를 의미합니다 .tac "$file" | grep -Em1 '\S'
:tac
응 카운트다운cat
. 파일의 내용을 인쇄하지만 마지막 줄부터 첫 번째 줄까지 인쇄합니다. 따라서 이 명령은 비어 있지 않은 마지막 줄을 인쇄합니다.