[리눅스/윈도] awk : 필드 1개만 제외하고 전체 줄 출력하기

2023. 7. 24. 05:58리눅스 실제 사용 팁/bash

AWK 를 활용하면서도 말끔히 해결되지 못하고 기억 속 저편에 남아 있던 내 숙제.

 

다음과 같은 데이터 목록이 있다.

$ history | grep sed > sed_grp
$ cat sed_grp
---
[실행결과]
369  sed -i '/.*노브랜드.*/s/$/ FOOD/g' PAY_LIST.txt
370  sed -i '/.*GS25.*/s/$/ CVS/g' PAY_LIST.txt
371  sed -i '/.*CU.*/s/$/ CVS/g' PAY_LIST.txt
372  sed -i '/.*이마트24.*/s/$/ CVS/g' PAY_LIST.txt
373  sed -i '/.*E-MART24.*/s/$/ CVS/g' PAY_LIST.txt
381  sed -i '/.*시장.*/s/$/ FOOD/g' PAY_LIST.txt
387  sed -i '/.*병원.*/s/$/ HOSPITAL/g' PAY_LIST.txt

카드 사용내역 중 비슷한 종류끼리 묶어서 합산한 후 어느 지출에 더 많이 나가는지 계산하기 위한 중간과정이다.

sed 실행내역만 뽑아서 스크립트 안에 넣을려고 하는데 맨 앞에 붙어 있는 history 내의 실행 순번을 제거하고 싶다.

그럼 간단히 $1 (첫 번째 필드)만 제거하고 나머지 $2 ... $7 (두 번째 필드부터 그 뒤.... 마지막 순번을 알아내서 For loop 으로 돌리면 되지 않냐고 하겠지. 아니면 긴 노가다를 이어서 하던가...

 

하지만, 만일 필드 개수가 적어도 15개 이상이라면 그 성가신 것을 어떻게 다 찍어내냐고?!

이를 테면,

$ awk '{print $2, $3, $3, $5, $6, $7, $8, $9, $10, $11, ...}'

(이거 찍으려다가 병나겠다)

 

다행히도 방법은 있었다. 아직 다듬어야 하겠지만.

$0 이 전체 문자열인데 여기서 gsub() 함수를 써서 $1 만 제외하면 된다. 그 뒤에 붙는 필드 구분자는 다음에...

 

$ awk '{gsub($1, "", $0);print $0}' sed_grp

또는

$ awk '{$1="";print $0}' sed_grp
(의외로 이렇게 더 쉬운 방법이 있었다)
---
[실행결과]
  sed -i '/.*노브랜드.*/s/$/ FOOD/g' PAY_LIST.txt
  sed -i '/.*GS25.*/s/$/ CVS/g' PAY_LIST.txt
  sed -i '/.*CU.*/s/$/ CVS/g' PAY_LIST.txt
  sed -i '/.*이마트24.*/s/$$/ CVS/g' PAY_LIST.txt
  sed -i '/.*E-MART24.*/s/$/ CVS/g' PAY_LIST.txt
  sed -i '/.*시장.*/s/$/ FOOD/g' PAY_LIST.txt
  sed -i '/.*병원.*/s/$/ HOSPITAL/g' PAY_LIST.txt

 

남은 과제는 저 sed 앞에 붙은 FS 변수에 해당하는 여백을 없애는 것이다. stackoverflow 에서는 awk 로 해결할 방법이 없다는데

일단은 sed 로 걸러내는 수 밖에..

 

$ awk '{$1="";print $0}' sed_grp | sed 's/[[:space:]]//g'
---
[실행결과]
sed -i '/.*노브랜드.*/s/$/ FOOD/g' PAY_LIST.txt
sed -i '/.*GS25.*/s/$/ CVS/g' PAY_LIST.txt
sed -i '/.*CU.*/s/$/ CVS/g' PAY_LIST.txt
sed -i '/.*이마트24.*/s/$$/ CVS/g' PAY_LIST.txt
sed -i '/.*E-MART24.*/s/$/ CVS/g' PAY_LIST.txt
sed -i '/.*시장.*/s/$/ FOOD/g' PAY_LIST.txt
sed -i '/.*병원.*/s/$/ HOSPITAL/g' PAY_LIST.txt