쉘 스크립트의 awk

쉘 스크립트의 awk
#
# Script Name : extract_filename.ksh
#
#!/bin/ksh

FILE_TO_SPLIT="CR_WKLY_Sales_SC_ON.TXT"
FILE_TO_SPLIT_NEW=$(awk FILE_TO_SPLIT_AWK="$FILE_TO_SPLIT" -F'[_.]' '{print $1"_"$3"_"$4"_"$5}')
echo "$FILE_TO_SPLIT_NEW"

다음 명령은 Unix 명령 프롬프트에서 제대로 실행되고 원하는 출력을 얻습니다.

echo "CR_WKLY_Sales_SC_NC.txt" | awk -F'[_.]' '{print $1"_"$3"_"$4"_"$5}'

여기에 이미지 설명을 입력하세요.

추출하려고 하는데CR_Sales_SC_ON.TXT위 스크립트에서 파일 이름에서 "WKLY"를 제거하면 내가 뭘 잘못하고 있는 걸까요...?

억제하는 다른 좋은 방법이 있나요?왕 켈리문자열CR_WKLY_Sales_SC_ON.TXT쉘 스크립트의 문자열..?

WKLY내 예를 보여주기 위해 무엇이든 될 수 있습니다. 우리의 요구 사항은 첫 번째 " _"(밑줄)과 두 번째 " _"(밑줄) 사이에 억제된 문자열을 추출하는 것입니다.

예를 들어.

CR_MNTHLY_In2_SC_NC.txt
CR_WKLY_Sales_ST_NC.txt
CR_YRLY_In2_ST_NC.txt
CR_DLY_ITr_SC_NC.txt

원하는 출력은 다음과 같아야 합니다.

CR_In2_SC_NC.txt
CR_Sales_ST_NC.txt
CR_In2_ST_NC.txt
CR_ITr_SC_NC.txt

답변1

밑줄 중 하나도 제거하고 싶다고 가정합니다. 다음을 사용하는 솔루션은 다음과 같습니다 sed.

$ echo CR_WKLY_Sales_SC_ON.TXT | sed 's/WKLY_//'
CR_Sales_SC_ON.TXT

답변2

필수 인가요 awk?

sed작업에 적합한 직관적인 대체 사용

sed -e 's/\(^[^_]*\)_[^_]*\(.*\)/\1\2/' u
CR_In2_SC_NC.txt
CR_Sales_ST_NC.txt
CR_In2_ST_NC.txt
CR_ITr_SC_NC.txt

u파일(또는 입력)은 어디에 있습니까?

단일 변수의 경우

FILE_TO_SPLIT_NEW=$(echo "$FILE_TO_SPLIT" | sed -e 's/\(^[^_]*\)_[^_]*\(.*\)/\1\2/')

sed 구문:

  • /\(^[^_]*\)_[^_]*\(.*\)/이 필터는 Pattern1_pattern2_rest이며, 여기서 패턴과 나머지에는 _.
    • [^_]*"밑줄을 제외한 모든 횟수, 횟수 제한"을 의미합니다.
    • 모드 1과 나머지는 변수에 할당됩니다.\(...\)
  • /\1\2/변수 확장
  • -e개별 대체는 생략 가능

답변3

실제 문제는 변환하려는 문자열을 awk스크립트의 호출로 전달하는 방법이라고 생각합니다. 이것이 FILE_TO_SPLIT_AWK="$FILE_TO_SPLIT"@terdon이 이것이 무엇을 의미하는지 질문하는 이유입니다.

올바른 방법 중 하나는 다음과 같습니다.

FILE_TO_SPLIT_NEW=$(echo "$FILE_TO_SPLIT" | awk -F'[_.]' '{print $1"_"$3"_"$4"_"$5}')

.txt또한 명령줄 예제에서는 그렇지 않은 파일 이름 접미사(귀하의 경우)가 출력에 남아 있기를 원하므로 다음 을 수행해야 합니다.

  • .필드 구분 기호 목록에 마침표를 포함하지 마십시오.

  • 마지막 필드도 인쇄합니다.

그래서 어느 쪽이든

  • awk -F'_' '{print $1"_"$3"_"$4"_"$5}', 또는

  • awk -F'[_.]' '{print $1"_"$3"_"$4"_"$5"."$6}'

어쨌든 "_"로 구분된 실제 필드 수와 무관하고 두 번째 필드만 계산하려는 경우 다음 예가 작동합니다.

FILE_TO_SPLIT_NEW=$(echo "$FILE_TO_SPLIT" | awk '{match($0,"^([^_]+)_([^_]+)_([[:print:]]*)$",a); print a[1]"_"a[3]}')

부록

파이프 사용으로 인한 컨텍스트 전환을 피하려면 먼저 변환하려는 파일 이름을 임시 파일로 작성한 다음 awk메모리 내 변수 대신 해당 파일에서 작업할 수 있습니다.

echo $FILE_TO_SPLIT > tmpfile.txt
FILE_TO_SPLIT_NET=$(awk '{match($0,"^([^_]+)_([^_]+)_([[:print:]]*)$",a); print a[1]"_"a[3]}' tmpfile.txt)

그러나 (물론 특정 사용 사례에 따라) 모든 "원본" 파일 이름을 파일에 쓰고, awk해당 파일에 대해 작업하고, 결과를 한 줄씩 읽어 변환된 모든 파일 이름을 처리할 수 있습니다.

답변4

아마도

cut -d_ -f1,3- file

-d_구분 기호 및 출력 -f필드 1, 3 이상 설정1,3-

산출

CR_In2_SC_NC.txt
CR_Sales_ST_NC.txt
CR_In2_ST_NC.txt
CR_ITr_SC_NC.txt

변수/문자열에

cut -d_ -f1,3- <<<"CR_Banana_IN2_SC_NC.txt"

또는

echo "CR_Banana_IN2_SC_NC.txt" | cut -d_ -f1,3-

관련 정보