내 웹 서버 로그 파일은 다음과 같습니다.
2001:67c:1220:80c:d4:985a:df2c:d717 - - [22/Feb/2019:07:49:01 +0100] "GET / HTTP/1.1" 200 58266 "-" "curl/7.61.1"
2001:67c:1220:80c:d4:985a:df2c:d717 - - [22/Feb/2019:08:49:01 +0100] "GET / HTTP/1.1" 200 58341 "-" "curl/7.61.1"
2001:67c:1220:808::93e5:8ad - - [22/Feb/2019:08:56:10 +0100] "POST /wp-cron.php?doing_wp_cron=1550822170.2184400558471679687500 HTTP/1.1" 200 3279 "https://ios-example.com/wp-cron.php?doing_wp_cron=1550822170.2184400558471679687500" "WordPress/4.9.9; https://ios-example.com"
...
이 형식으로 날짜와 시간을 추출해야 합니다 22/Feb/2019:07:49:01
.
이것이 내가 지금 가지고 있는 것입니다(이 스레드에서 뻔뻔하게 복사했습니다:행에서 날짜 필드 추출):
file="filename"
while IFS= read -r line
do
echo "`cut -d '[' -f2 $line | cut -d ' ' -f1`" # echoing now for testing purposes
done <"$file"
스크립트를 실행할 때의 출력은 다음과 같습니다.
cut: '2001:67c:1220:80c:d4:985a:df2c:d717': Adresář nebo soubor neexistuje
cut: '[22/Feb/2019:07:49:01': Adresář nebo soubor neexistuje
cut: +0100]: Adresář nebo soubor neexistuje
cut: '"GET': Adresář nebo soubor neexistuje
cut: /: je adresářem
cut: 'HTTP/1.1"': Adresář nebo soubor neexistuje
cut: 200: Adresář nebo soubor neexistuje
cut: 58266: Adresář nebo soubor neexistuje
cut: '"-"': Adresář nebo soubor neexistuje
cut: '"curl/7.61.1"': Adresář nebo soubor neexistuje
22/Feb/2019:08:49:01
22/Feb/2019:08:56:10
22/Feb/2019:08:56:10
22/Feb/2019:09:24:33
22/Feb/2019:09:24:33
22/Feb/2019:09:43:13
22/Feb/2019:09:43:24
...
"Adresář nebo soubor neexistuje"는 "디렉토리나 파일이 존재하지 않습니다"를 의미합니다.
나에게 알려지지 않은 이유로 인해 로그 파일의 첫 번째 줄에서는 작동하지 않지만 파일의 나머지 부분에서는 작동합니다.
답변1
여러 가지 실수를 저질렀습니다.
- cut은 파일 이름을 인수로 사용합니다.
- 큰따옴표를 잊어버렸습니다(")
따라서 최소한의 변경으로 예제를 다시 작성하면 다음과 같습니다.
- 어떤 것의 목적을 가리킨다.$(바꾸다`. 이는 더욱 강력하며 재귀적으로 작동합니다.
- 어떤 것의 목적을 가리킨다.${VARIABLE_NAME}$VARIABLE_NAME 대신. 이게 더 튼튼해요
새로운 버전
file="filename"
while IFS= read -r line
do
EXTRACT_DATE=$( echo "$line" | cut -d '[' -f2 | cut -d ' ' -f1 )
echo "${EXTRACT_DATE}"
done <"$file"
답변2
오류를 일으키는 주요 문제는 읽기 행을 에서 읽을 $line
파일 이름 으로 사용하고 있다는 것입니다.cut
echo
이를 사용하여 명령 대체 결과를 출력 할 수도 있습니다 . 이것은 안티 패턴입니다. 파이프라인을 실행하기만 하면 됩니다. 명령을 바꿀 필요가 없습니다 echo
. 결과를 자체적으로 터미널에 출력합니다.
여기서는 다음을 사용하여 파일에서 읽은 행을 printf
제공합니다 .cut
file="filename"
while IFS= read -r line; do
printf '%s\n' "$line" | cut -d '[' -f2 | cut -d ' ' -f1
done <"$file"
다음으로 주목해야 할 점은 while
루프가 완전히 불필요하다는 것입니다. cut
두 번 전화를 걸었 습니다.각 라인로그 파일에 있습니다. 이 cut
유틸리티는 자체적으로 파일을 한 줄씩 읽을 수 있습니다.
file="filename"
cut -d '[' -f2 "$file" | cut -d ' ' -f1
또는 GNU를 사용할 수도 있습니다 grep
.
grep -oP '(?<=\[)[^ ]+' "$file"
(이렇게 하면 첫 번째 공백 이후부터 첫 번째 공백 이전의 모든 내용이 추출됩니다 [
.)
또는 표준 sed
,
sed 's/\].*//; s/.*\[//; s/ .*//' "$file"
(이렇게 하면 첫 번째 이후의 모든 항목이 제거되고 ]
첫 번째 이후의 모든 항목이 제거 [
된 다음 공백과 나머지가 제거됩니다.)
관련된: