간단한 스크립트를 리팩터링하여 파이프 가능하게 만드는 방법(표준 출력에서 ​​입력 가져오기)

간단한 스크립트를 리팩터링하여 파이프 가능하게 만드는 방법(표준 출력에서 ​​입력 가져오기)

다음 스크립트가 있습니다.

#!/bin/bash

file=$1

echo "Phone:" 
read phone
echo
echo "Column:"
read column
echo
echo "New Value:"
read value
echo

index=$(cat $file | grep -n $phone | cut -d: -f1)

cat "$file" | awk -v idx="$index" -v col="$column" -v value="$value" -F ',' '{if (NR==idx) {for(i=1;i<=NF;i++) {if (i==col) $i=value; printf("%s%s", $i, (i==NF ? "\n":FS))}} else print}'

echo

exit 0

파일을 수신하고 사용자에게 숫자, 열 및 새 값을 묻는 메시지를 표시한 다음 해당 특정 필드를 업데이트합니다. 내 문제는 다음과 같이 호출해야 한다는 것입니다.

./update.sh data.csv

스크립트를 별칭으로 변환하고 사용자에게 값을 묻는 대신 플래그를 사용하여 파이프할 수 있기를 원했기 때문에 사용자 정의 플래그(열의 경우 -c, 값의 경우 -v, 필터링된 패턴의 경우 -e)를 추가했습니다. 예를 들어:

cat data.csv | update -c 2 -v "value" -e "pattern"

누군가 스크립트를 플래그가 있는 별칭으로 변환하는 방법을 안내해 줄 수 있습니까? (별칭은 명령을 참조합니다. 별칭을 잘못 사용한 것일 수 있습니다.)

그리고 저는 아직 bash, awk, linux를 배우고 있으니 제가 잘못하고 있거나 비효율적으로 하고 있는 부분을 발견하시면 바로잡아주세요.

미리 감사드립니다

p.s 어쩌면 도움이 될 수도 있습니다. data.csv는 다음과 같습니다.

444-555-7777, Max,Weaver, personal:friend:musician
111-222-6665, Craig,Kowalick,office:friend
888-797-2345,Tom, O’Brien, personal:family:musician:midnightsociety

답변1

사용선택 항목 가져오기매개변수를 구문 분석한 다음 awkCSV 필드와 유사하게 일치시킵니다(예: 테스트되지 않음).

#!/usr/bin/env bash

while getopts ":p:c:v:e:" arg; do
    case $arg in
        p) phone=$OPTARG ;;
        c) col=$OPTARG ;;
        v) val=$OPTARG ;;
        e) ere=$OPTARG ;;
        *) printf 'Unknown argument "%s"\n' "$arg" >&2
           exit 1
           ;;
    esac
done
shift $((OPTIND-1))

그런 다음 awk를 사용하여 CSV로 원하는 작업을 수행합니다. 예를 들어 (다시 한번 테스트되지 않았으며 단지 예일 뿐이며 실제로 원하는 작업을 수행하려는 의도는 없습니다. 위의 변수는 단지 사용 방법을 보여주기 위한 것입니다.)

awk -v phone="$phone" -v col="$col" -v val="$val" -v ere="$ere" '
    BEGIN { FS=OFS="," }
    ($1 == phone) && ($0 ~ ere) && ($col == val) {
        print "Matched: " $0
    }
' "${@:--}"

이는 "${@:--}"파일 이름이 전달되면 awk에게 filename에서 읽도록 지시하고, 그렇지 않으면 stdin에서 읽도록 지시합니다.

위에 표시된 대로 awk 스크립트에서 사용하기 전에 모든 필수 변수가 채워졌는지 확인하려면 쉘 스크립트 또는 awk 스크립트에 일부 코드를 추가해야 할 수도 있습니다. getopts 루프와 awk 호출 사이에 다음 셸 코드를 추가할 수 있습니다.

while [[ -z "$phone" ]]; do
    echo "Phone:" 
    read -r phone
done

변수가 프롬프트+응답으로 채워졌는지 확인하세요(명령줄에서 아직 설정되지 않은 경우).

나는 위에서 귀하의 질문에 있는 "패턴"을 통해 전체 라인 확장 정규식 일치를 수행하기를 원한다고 가정하고 있습니다. 이것이 바로 관련 변수 ere또는 pat이와 유사한 이름을 지정한 이유입니다. 직관에 어긋난다는 건 알지만, 요구 사항을 명시하거나 패턴 일치 코드를 작성할 때 "패턴"이라는 단어를 사용하지 마세요. 마치 자동차 판매점에 가서 세일즈맨에게 "자동차"를 사고 싶다고 말하는 것처럼 매우 모호합니다. 어떤 컨텍스트에서 어떤 패턴을 일치시키려는지 구체적으로 알아보려면 다음을 참조하세요.패턴과 일치하는 텍스트를 찾는 방법.

관련 정보