특정 필드의 텍스트를 루프의 변수로 바꾸기

특정 필드의 텍스트를 루프의 변수로 바꾸기

텍스트를 구문 분석하고 검색하고 바꿔야 하는 대용량 파일이 있지만 특정 필드에서는 참조용으로 dest라는 작은 샘플을 공유합니다. 첫 번째 줄은 참조용 제목입니다.

cat dest
ID|NAME|COMPANY|NUMBER
1001|Adam||15001
1002|eve|adam&eve|15002
1003|||
1004|||50000
1005|||50001

일치시킬 패턴, 바꿀 텍스트, 바꿀 텍스트가 포함된 별도의 파일이 있습니다.

cat src
1003||15003
1004|50000|15004
1005|50001|15005

따라서 sed를 사용하여 src 파일의 마지막 2줄에 대해 아래에 제공된 while 루프를 실행할 수 있습니다.

cat src | while IFS=$'|'; read id old new; do sed -i "/^${id}/s/${old}/${new}/" dest; done

그러나 ID=1003내가 얻은 빈 문자열 의 경우 $olddest 파일에서 해당 ID에 대한 모든 빈 열을 대체합니다. 나는 이런 상황을 피하고 싶다. 내가 원하는 것은 마지막 필드만 바꾸는 것입니다.

예상하다:

ID|NAME|COMPANY|NUMBER
1001|Adam||15001
1002|eve|adam&eve|15002
1003|||15003
1004|||15004
1005|||15005

열 형식 데이터에 대해 더 세분화되어 있으므로 awk를 사용할 수 있습니다. 그러나 내가 아는 한 awk는 stdout으로 여러 번 인쇄하는데 이는 나에게도 실용적이지 않습니다.

그렇다면 이 작업을 현명하고 간결하게 수행할 수 있는 방법이 있을까요?

답변1

awk 'BEGIN{ FS=OFS="|" }
 NR==FNR  { id[$1, $2]=$3; next }
          { $4=( ($1, $4) in id? id[$1, $4]: $4) } 1' src dest
  • FS:에프생산하다에스반복자

  • OFS:산소산출에프생산하다에스반복자

  • NR==FNR: 첫 번째 입력 파일에 대해 항상 참인 조건부 관용구입니다.

    NR 총 존재 수질소수량오른쪽FNR 이 읽은 기록
    은 모든 사람에게 존재합니다 .에프엘리스질소수량오른쪽기록.

  • id[$1, $2]=$3:관련 awk 배열.

    이름: id
    키: 열#1+열#2
    값: 열#3

    첫 번째 블록은 첫 번째 입력 파일에 대해서만 실행됩니다. 마. 서류소스 코드.

여기서는 $4=($1, $4) in id? id[$1, $4]: $4두 번째 파일 i의 마지막 열( $NFor )의 값을 업데이트합니다 $4. 마. 서류목적지열#1+열#4의 일치하는 키 조합ID배열은 발견되면 값( )을 반환하고 id[$1, $4], 그렇지 않으면 현재 값을 복사합니다.

답변2

또 다른 awk솔루션은 행이 src순서대로 한 번만 사용된다고 가정합니다. 이를 통해 우리는 src사용할 때까지 다음 줄을 추적하고 다음 줄을 읽을 수 있습니다 .

awk -F '|' '
    BEGIN { OFS=FS }
    ! have {
        getline line <"src"
        split(line, pat)
        have = 1
    }
    $1 == pat[1] {
        if ($4 == pat[2]) $4 = pat[3]
        have = 0
    }; 1' dest

이 플래그가 have설정되지 않거나 0이면 src다음 줄을 읽고 line배열로 분할 합니다 pat. 이것은 ! have블록 단위로 수행됩니다.

현재 입력 라인의 dest첫 번째 필드 가 의 첫 번째 요소와 동일 pat하면 네 번째 필드를 테스트하고 pat[2]동일한 경우 이를 대체합니다. 그런 다음 pat[3]플래그 는 have0으로 재설정되어 에서 새 줄 읽기를 트리거합니다 src.

1프로그램 끝에서 후행하면 awk(수정될 수 있는) 레코드가 출력됩니다.

질문의 데이터 출력을 제공합니다.

ID|NAME|COMPANY|NUMBER
1001|Adam||15001
1002|eve|adam&eve|15002
1003|||15003
1004|||15004
1005|||15005

관련 정보