주문별 결제 내역 대조하기

LinuxBeginner
지금 연습하기

소개

EARLY CRUMB는 토요일 빵 수령을 준비하고 있습니다. 주문, 결제, 취소 기록은 서로 다른 파일에 있습니다. 이름이 같은 고객도 있고, 한 주문에 여러 상품이 들어갈 수도 있습니다. 쓸 수 있는 인계 목록을 만들려면 이름으로 추측하기보다 올바른 기록을 연결해야 합니다.

이 실습에서는 주문과 결제 표를 준비하고, 모든 주문 ID를 결제 상태와 연결한 다음, 결제 완료 ID 목록을 만듭니다. 취소 처리는 다음 독립 실습에서 다룹니다. 기본적인 터미널 사용 경험만 있으면 됩니다. 탭, 필드, 정렬과 각 명령은 사용하기 전에 설명합니다. 모든 인물과 기록은 가상입니다.

명령은 Workstation에서 실행하고, 준비된 수령 데스크는 Pickup Preview에서 확인합니다. 미리보기에는 원본 기록과 예시 라벨이 표시됩니다. 정답을 계산하거나 파일을 대신 만들어 주지는 않습니다.

연결할 수 있는 표 준비하기

이 단계에서는 상품 행을 하나도 잃지 않으면서 머리글 없는 기록과 정렬된 주문 ID 목록을 준비합니다. Pickup Preview에서 시작하세요.

인계에 필요한 정보 이해하기

Sample label을 여세요. EX050은 Sam의 주문이며 호밀빵 한 개가 들어 있습니다. 이것은 별도의 예시이지 완성된 내 수령 목록이 아닙니다. 주문 코드는 봉투 하나를 식별하고, 이름은 고객이 자신의 봉투를 알아보게 합니다. 상품과 수량은 포장 담당자에게 무엇을 넣어야 하는지 알려 줍니다.

Records를 여세요. 상품 코드 rye는 Rye loaf, oat는 Oat cookie입니다. orders.tsv에서 P101을 찾으세요. Alex는 호밀빵 두 개와 오트 쿠키 한 개를 주문했습니다. P102도 Alex의 주문이지만 다른 주문이고 결제 상태는 unpaid입니다. 이름으로 연결하면 봉투를 잘못된 주문에 배정할 수 있습니다. order_id를 사용하세요.

주문 코드, 고객, 상품 수량이 있는 제공된 예시 라벨

준비된 파일 읽기

Workstation으로 전환하세요. 시작 디렉터리는 /home/labex/project/pickup입니다. pwd는 현재 디렉터리를 출력하고, ls는 그 안의 항목을 나열합니다.

pwd
/home/labex/project/pickup
ls

source와 work가 보여야 합니다. 원본 기록은 그대로 두고, 다시 만들어도 되는 중간 파일은 work/에 저장합니다. source/orders.tsv 같은 경로는 이 디렉터리를 기준으로 합니다. 다른 곳으로 이동했다면 다음 명령으로 돌아오세요.

cd /home/labex/project/pickup

cat은 파일 내용을 보여 줍니다. 두 표를 읽으세요.

cat source/orders.tsv
cat source/payments.tsv

TSV는 탭으로 구분된 값을 뜻합니다. 각 줄은 기록 하나이고, 탭은 필드를 구분합니다. 첫 줄은 머리글입니다. 주문에는 주문 ID, 고객, 상품, 수량이라는 네 필드가 있습니다. 한 주문에 여러 상품 행이 있을 수 있습니다. 결제에는 주문 ID와 정확한 상태 paid 또는 unpaid라는 두 필드가 있습니다. 주문당 결제 행은 최대 하나입니다. 준비된 형식에서 값 안에 탭이나 줄바꿈은 없습니다.

P106은 주문에 있지만 결제 행은 없습니다. 정보가 없다는 것은 결제 완료라는 뜻이 아닙니다. 연결할 때 이 사실이 드러나도록 유지합니다.

머리글과 기록 분리하기

tail -n +2는 두 번째 줄부터 출력합니다. >는 출력을 파일에 저장하며, 대상이 이미 있으면 덮어씁니다. 원본은 바꾸지 않습니다. >를 쓸 때 원본과 대상에 같은 경로를 지정하지 마세요. 프로그램이 읽기 전에 셸이 파일을 비워 버립니다.

tail -n +2 source/orders.tsv > work/orders.rows
tail -n +2 source/payments.tsv > work/payments.rows

상품 행을 확인하세요.

cat work/orders.rows

P101과 P105는 상품이 각각 두 가지이므로 두 번씩 나옵니다. 이 행들을 유지하세요. 주문 ID가 반복된다고 무조건 중복 데이터는 아닙니다.

연결 키 준비하기

키는 기록을 연결할 때 쓰는 필드입니다. cut -f1은 탭으로 나뉜 첫 필드를 선택합니다. 파이프 |는 출력을 다음 명령으로 보냅니다. sort -u는 줄을 정렬하고 완전히 같은 줄을 한 번씩만 남깁니다. 여기서는 상품 표가 아닌 ID 목록에만 적용합니다.

정렬과 연결은 같은 순서를 사용해야 합니다. LC_ALL=C는 예측 가능한 바이트 순서를 정하고, export는 뒤따르는 명령에도 그 설정을 전달합니다. 이 설정은 현재 터미널에 적용되므로 새 터미널을 열면 다시 지정하세요.

export LC_ALL=C
cut -f1 work/orders.rows | sort -u > work/order-ids.txt
cat work/order-ids.txt
P101
P102
P103
P104
P105
P106

두 필드인 결제 표는 상태를 유지한 채 첫 필드로 정렬합니다. TAB은 탭 하나를 담는 셸 변수입니다. printf '\t'가 탭을 출력하고 $(...)가 그 출력을 가져옵니다. "$TAB"의 큰따옴표는 이를 구분자 인자 하나로 전달합니다. -t는 필드 구분자, -k1,1은 첫 필드만 정렬 키로 지정합니다.

TAB=$(printf '\t')
sort -t "$TAB" -k1,1 work/payments.rows > work/payments.sorted.tsv
cat work/payments.sorted.tsv

P101부터 P105까지 원래 상태와 함께 순서대로 나와야 합니다. P106의 결제 행이 새로 생기지는 않습니다. 이제 서로 다른 주문 ID 여섯 개와 결제 기록 다섯 개가 모두 연결 준비를 마쳤습니다. 머리글이나 상태가 잘못되었다면 해당 작업 파일만 원본에서 다시 만드세요. 결과에 맞추려고 원본을 수정하지 마세요.

모든 주문을 결제 상태와 연결하기

이 단계에서는 준비한 두 입력을 결합하고, 결제가 없는 주문도 보이도록 남깁니다. 1단계에서 사용한 Workstation의 같은 터미널에서 시작하세요.

연결 결과의 의미 알기

P101은 paid, P102는 unpaid, P106은 명시적인 missing 값과 연결되어야 합니다. 이름은 연결에 쓰지 않습니다. 이 시점에는 결제 완료 주문도 취소되었을 수 있습니다. 결제 연결만으로 최종 수령 목록이 결정되지는 않습니다.

join은 기본적으로 정렬된 입력의 첫 필드를 연결합니다. 일반적인 내부 결합은 짝이 없는 ID를 생략합니다. 여기서는 누락된 기록도 봐야 합니다.

  • -t "$TAB"은 1단계에서 만든 탭 구분자를 사용합니다.
  • -a 1은 첫 입력인 전체 주문 ID 목록에서 짝이 없는 기록도 포함합니다.
  • -e missing은 출력 필드가 없을 때 missing이라는 단어를 넣습니다.
  • -o 1.1,2.2는 입력 1의 필드 1(주문 ID), 입력 2의 필드 2(상태)를 출력합니다. 1과 2는 줄 번호가 아니라 입력 파일입니다.

명령 전체를 한 줄로 실행하세요. 두 필드로 된 결과를 저장합니다.

join -t "$TAB" -a 1 -e missing -o 1.1,2.2 work/order-ids.txt work/payments.sorted.tsv > work/payment-match.tsv
cat work/payment-match.tsv
P101 paid
P102 unpaid
P103 paid
P104 paid
P105 paid
P106 missing

위 간격은 탭이며, 역슬래시와 t라는 문자 자체가 아닙니다. 여섯 행이 보여야 합니다. 왼쪽 입력에 모든 주문 ID가 있고 -a 1이 짝 없는 ID를 유지하므로 P106도 남아 있습니다.

필터링 전에 결과 읽기

원본에서 P101과 P102는 모두 Alex이지만 상태는 다릅니다. P103도 결제 완료이며, 이후 취소로 제외될 수 있습니다. P106에는 결제 기록이 없으므로 missing을 통해 비교에서 조용히 사라지는 일을 막습니다.

join이 입력이 정렬되지 않았다고 알리면 1단계로 돌아가 같은 LC_ALL=C 설정으로 두 정렬 입력을 다시 만드세요. 경고를 숨기거나 불편한 주문을 제거하지 마세요. 터미널에 다시 연결했다면 재시도 전에 디렉터리와 1단계의 두 셸 설정을 복구하세요.

명령 실행이 성공한 것만으로 충분하지 않습니다. 중요한 세 행을 원본 기록과 비교하세요. 이제 다음 판단에 쓸 완전한 결제 연결 결과가 있습니다.

주문을 구별하면서 결제 완료 주문 선택하기

이 단계에서는 결제 완료 주문 ID 파일을 만들고, 실제 저장한 내용을 확인합니다. Workstation에서 시작하세요.

상태 전체를 일치시키기

paid와 unpaid에는 모두 paid라는 글자가 들어 있습니다. 단순 문자열 검색은 P102를 잘못 포함합니다. 탭 다음에 완전한 상태가 나오고 줄이 끝나는 조건이 필요합니다.

grep은 일치하는 줄을 선택합니다. $'\tpaid$'에서 바깥쪽 $'...'는 \t를 탭 문자로 만들고, 표현식 안 마지막 $는 줄 끝을 뜻합니다. 따라서 상태 필드는 unpaid의 끝부분이 아닌 정확한 paid여야 합니다. 그다음 cut -f1이 주문 ID만 남깁니다. 연결 표가 정렬되어 있으므로 출력도 이미 정렬된 상태입니다.

grep $'\tpaid$' work/payment-match.tsv | cut -f1 > paid-order-ids.txt
cat paid-order-ids.txt
P101
P103
P104
P105

P102는 미결제이고 P106은 결제 기록이 없으므로 여기 들어가지 않습니다. 이 단계에서는 P103을 유지하세요. 이 파일은 결제 완료 주문을 뜻하며, 포장할 최종 주문 집합은 아닙니다. 취소를 보기 전에 제거하면 두 판단을 섞어 중간 결과의 의미가 틀어집니다.

저장한 선택 결과 읽기

Pickup Preview로 전환하세요. 탐색 메뉴에서 Payment IDs를 선택하세요. 이 페이지는 paid-order-ids.txt를 표시할 뿐 결제 정답을 계산하지 않습니다. 방금 저장한 네 ID가 보여야 합니다. Compare with source records를 따라가 해당 결제 행을 확인하세요.

준비된 미리보기의 Pickup list에는 아직 포장 목록이 없다고 나올 수 있습니다. 정상입니다. 최종 상품 목록이 아니라 결제 선택 결과를 만들었기 때문입니다. 다음 독립 실습에서는 이 결과로 취소를 제외하고 모든 유효 상품의 수량을 보존합니다.

파일이 비었거나 P102가 들어 있다면 work/payment-match.tsv와 정확한 상태 패턴을 확인한 후 필터 명령을 다시 실행하세요. 원본 기록을 바꾸지 않고 결과를 수정하고 다시 만들 수 있습니다.

요약

탭으로 구분된 기록을 준비하고, 공통 키로 정렬하고, 누락 기록을 유지하면서 결제를 연결하고, 정확한 결제 완료 상태를 선택했습니다. 주문의 식별 정보와 고객 이름, 상품 행을 구분했습니다. 다음 독립 실습에서는 이 결제 선택 결과를 실제 수령 인계 목록으로 바꿉니다.