sed를 사용하여 열 1과 7의 패턴을 기반으로 csv 파일의 결과를 필터링하려면 어떻게 해야 합니까?

sed를 사용하여 열 1과 7의 패턴을 기반으로 csv 파일의 결과를 필터링하려면 어떻게 해야 합니까?

사용자 지정 값에 대해 열 1과 7을 검색하는 쉘 스크립트를 작성하려고 합니다. 여기서 $3은 열 7의 연도와 일치하고 $2는 열 1의 연도와 일치합니다($1은 파일 이름). 일곱 번째 열은 잘 일치시킬 수 있지만 첫 번째 열에 일치시킬 변수를 추가하려고 하면 'sed: -e 표현식 #1, char 7:unknown command: `2' 오류가 계속 발생합니다. 안타깝게도 awk 대신 sed를 사용해야 합니다. 이것이 내가 지금까지 가지고 있는 것입니다:

sed -n "/"$2",[^,],[^,],[^,],[^,],[^,]*,"$3"/p" "$1"

이 문제를 어떻게 해결해야 합니까? 저는 초보자이므로 모든 도움을 환영합니다. Shellcheck를 시도했지만 도움이 되지 않았습니다. 열 7을 스캔할 때 스크립트는 제대로 작동하지만 $2 측면을 추가하면 오류가 발생합니다.

편집: 예시 호출:

./script.sh filename "2015.2016" "South"

예제 파일("..."은 내부에 텍스트가 있는 열입니다):

2021/2022,text,text,text,text,text,South,text,...,...
2021/2022,text,text,text,text,text,North,text,...,...
2015/2016,text,text,text,text,text,South,text,...,...
2014/2015,text,text,text,text,text,West,text,...,...

예상 출력:

2015/2016,text,text,text,text,text,South,text,...,...

편집: 이것이 실제로 작업에 가장 적합한 도구는 아니라는 점에 동의하지만, 잠시 놀다가 sed를 사용하여 이 작업을 수행하는 방법을 알아냈습니다.

#!/bin/bash

year="$2"
name="$3"

sed -n '/^'"$year"',\([^,]*,\)\{5\}'"$name"'\(,.*\)\{0,\}$/p' "$1" 

제가 사용할지는 모르겠지만 다른분께는 도움이 될 것 같습니다. 정확한 결과를 생성하려면 입력에 "/" 대신 "."이 필요합니다.

답변1

sed는 그다지 좋은 도구가 아닙니다. 그냥 awk를 사용하세요.

$ cat script.sh
#!/usr/bin/env bash

awk -F',' '$1==a && $7==b' a="$2" b="$3" "$1"

$ ./script.sh file.csv "2021" "South"
2021,text,text,text,text,text,South,text

그러나 sed 솔루션이 필요하므로 POSIX sed를 사용하십시오.

$ cat script.sh
#!/usr/bin/env bash

a=$(sed 's/[^^\\]/[&]/g; s/\^/\\^/g; s/\\/\\\\/g' <<< "$2")
b=$(sed 's/[^^\\]/[&]/g; s/\^/\\^/g; s/\\/\\\\/g' <<< "$3")
sed -n '/^'"$a"',\([^,]*,\)\{5\}'"$b"'\(,.*\)\{0,\}$/p' "$1"

$ ./script.sh file.csv "2021" "South"
2021,text,text,text,text,text,South,text

바라보다sed를 사용하여 정규식 메타문자를 안정적으로 이스케이프하는 것이 가능합니까?처음 두 개의 sed 명령이 필요한 이유는 간단히 말해 리터럴 문자열 일치를 수행해야 하고 sed는 리터럴 문자열 일치가 아닌 정규식 일치만 지원하므로 가능한 모든 정규식 메타 문자를 이스케이프해야 하기 때문입니다(실제로 모든 문자를 이스케이프해야 합니다. char는 sed 스크립트 구분 기호(예 /: )일 수 있어 리터럴 문자처럼 동작하게 합니다. 이것은 리터럴 문자열 일치만 지원하는 awk와 같은 도구와 달리 sed가 작업에 대한 잘못된 도구라는 두 번째 큰 단서입니다(첫 번째는 입력을 필드로 분할하지 않는다는 것입니다).

관련 정보