Bash에서 파일 이름의 다른 필드를 추출하는 방법은 무엇입니까?

Bash에서 파일 이름의 다른 필드를 추출하는 방법은 무엇입니까?

병합하고 싶은 로그 파일이 몇 개 있습니다. 파일 이름의 형식 environment.type-YYYY-MM-DD.log은 다음과 같습니다.

  • environment서버의 환경을 나타냅니다: "private", "public", "para" 등)
  • type"주요", "사소한", "오류" 등입니다.
  • YYYY-MM-DD파일 생성 날짜를 나타냅니다.

모든 파일 유형은 모든 서버에서 발견됩니다. "기본", "부" 및 "오류" 파일은 개인, 공용 및 준 서버에서 발견됩니다. private.error-2021-09-10.log, , , .public.error-2021-09-11.log​​public.primary-2021-09-08.logpublic.error-2021-15.log

서로 다른 서버에 동일한 유형의 파일이 있을 수 있으므로 공용, 개인 및 파라 서버의 기본 파일을 별도로 융합해야 하며 오류 파일과 보조 파일에 대해서도 동일한 작업을 수행해야 합니다. 파일은 특정 날짜 범위 내에서 균등하게 병합되어야 합니다(매월 7일마다 한 파일씩 병합).

내 접근 방식은 다음 조건을 사용하는 것입니다.

  1. 서버 이름(public, private, para)을 파일 이름과 비교하여 해당 서버에 따라 파일을 그룹화합니다.
  2. 파일명에 있는 파일형식(오류, 메이저, 마이너)을 비교하여 각 서버에서 해당형식의 파일만 융합합니다.
  3. 날짜 범위를 비교하세요(융합된 파일을 받으려면 한 달에 최대 7일).

이렇게 하려면 조건에 포함할 값과 비교할 서버 이름, 파일 유형 및 날짜를 ​​추출하고 위 방법에 설명된 대로 파일을 개별적으로 융합하는 몇 가지 명령이 필요합니다.

나는 다음을 사용해 보았습니다. *.log | awk -F'[_.]' '{print $1}'환경 추출(필드 1) 부분을 사용하고 *.log | awk -F'[_.]' '{print $2}'파일 형식(필드 2)을 추출하려고 시도했지만 작동하지 않았습니다.

답변1

예제 파일 이름 세트를 사용하여:

private.error-2021-09-10.log
public.error-2021-09-11.log
public.primary-2021-09-08.log
public.error-2021-15.log

마지막 파일 이름에 누락된 "-MM-" 부분이 오타인 것 같습니다.

다음은 귀하에게 적합한 awk를 사용하는 예입니다.

"환경"을 얻으십시오:

ls *.log | awk -F'[.-]' '{print $1}'

결과:

private
public
public
public

"유형" 가져오기:

ls *.log | awk -F'[.-]' '{print $2}'

결과:

error
error
error
primary

날짜 스탬프 받기:

ls *.log | awk -F'[.-]' '{print $3 "-" $4 "-" $5}'

결과:

2021-09-10
2021-09-11
2021-15-log
2021-09-08

편집하다: 아래 설명에서 출력을 구문 분석하지 않는 옵션을 추가하고 싶습니다. ls이는 다른 문제가 발생하기 쉽기 때문입니다.

다음을 시도해 볼 수 있습니다.

for file in *.log; do
  echo "$file" | awk -F'[.-]' '{print $1}'
  echo "$file" | awk -F'[.-]' '{print $2}'
  echo "$file" | awk -F'[.-]' '{print $3 "-" $4 "-" $5}'
done

또는 find( find -type f -name "*.log" -exec awk -f'[.-]' '{print $1}' {} +;)를 사용하지만, 주의해야 할 몇 가지 문제가 있습니다.

답변2

로그 파일이 모두 파일 이름 와일드카드 패턴과 일치한다고 가정하면 *.*-*.log해당 이름을 반복하여 여러 부분을 별도의 변수로 추출할 수 있습니다.

for name in *.*-*.log; do
        tmpname=$name

        environment=${tmpname%%.*}; tmpname=${tmpname#*.}
        type=${tmpname%%-*};        tmpname=${tmpname#*-}
        date=${tmpname%.log}

        printf '"%s" --> %s + %s + %s\n' \
                "$name" "$type" "$environment" "$date"
done

이 코드는 이름의 여러 부분을 세 개의 변수 및 로 추출 합니다 environment. 우리는 연속적인 단계를 사용하여 이름 사본에서 각 부분을 추출하고 제거합니다 . 우리는 여러 번 사용하는 것보다 빠른 표준 매개변수 대체를 사용하고 있습니다 .typedatetmpnameawk

다음 예제를 실행하세요:

$ ls
list                                public.error-2021-15.log
private.error-2021-09-10.log        public.primary-2021-09-08.log
public.error-2021-09-11.log         script
$ ./script
"private.error-2021-09-10.log" --> error + private + 2021-09-10
"public.error-2021-09-11.log" --> error + public + 2021-09-11
"public.error-2021-15.log" --> error + public + 2021-15
"public.primary-2021-09-08.log" --> primary + public + 2021-09-08

관련 정보