arg가 파일인지 확인하고 그에 따라 인쇄하십시오.

arg가 파일인지 확인하고 그에 따라 인쇄하십시오.

arg를 통해 또는 파일이 존재하지 않는 경우 stdin에서 파일을 받는 다음 코드가 있습니다.

file=
column=
pattern=
path=
cmd="echo"

while getopts "f:c:e:" opt; do
        case $opt in
                f) file="$OPTARG";;
                c) column="$OPTARG";;
                e) pattern="$OPTARG";;
                *) echo "Usage: $0 -f [file] -c [column] -e [pattern]"
        esac
done

if [ -z "$file" ]; then
        file=$(cat)
fi

이 접근 방식의 문제점은 cat이 파일이 아닌 파일에서는 작동하지 않는다는 것입니다. 예를 들어 stdout에서 가져온 경우:

cat data.csv | ./read.sh -c 2 -e " Max"

그러면 다음을 실행할 수 없습니다.

cat "$file"

Bash 스크립트에서는 대신 echo를 사용해야 합니다.

OTOH, 파일이라면 cat을 사용할 수 있고 모든 것이 괜찮습니다. 내 질문은 스크립트가 var $file이 실제 파일 이름인지 또는 stdout인지 인식하도록 만드는 방법입니다.

편집: 의견과 답변을 고려했으며 사용자가 지정하는 열과 정규식을 읽고 표준 입력이나 인수로 전달된 파일에서 고려할 수 있는 전체 스크립트를 사용자에게 제공하는 방법은 다음과 같습니다.

#!/bin/bash

unset -v column pattern filepath
cmd=echo

DELIMITER=","

while getopts "f:c:e:" opt; do
        case $opt in
                f) file="$OPTARG";;
                c) column="$OPTARG";;
                e) pattern="$OPTARG";;
                *) printf>&2 '%s\n' "Usag: $0 [-f file] [-c column] [-e pattern]"; exit 1
        esac
done

if [ -z "$file" ]; then
        file=$(cat)
elif [ -z "$column" ]; then
        echo "column number neeeded!"
elif [ -z "$pattern" ]; then
        echo "pattern needed!"
fi

if [ -f "$file" ]; then
        cmd="cat"
fi

if [ "$column" -eq 5 ]; then
        DELIMITER=":"
fi

"$cmd" "$file" | awk -v col="$column" -v pattern="$pattern" -v del="$DELIMITER" -F "$DELIMITER" '{
        for (i=1;i<=NF;i++) {
                if ( i == col && $i == pattern ) {
                        print $0
                } else if ( del == ":" && $i == pattern ) {
                        print $0
                }
        }       
}'

exit 0

작동하지만 올바른 접근 방식이 아니라고 확신합니다. 내 파일에서 두 가지 작업을 모두 수행하도록 다시 시도했습니다.

cat data.csv | ./read.sh -c 2 -e "Max"

그리고:

./read.sh -f data.csv -c 2 -e "Max"

위의 스크립트는 작동하지만 최적화가 게임의 이름입니다!

답변1

의 경우 cat표준 -입력을 의미합니다. 많은 시스템에서 이 /dev/stdin명령은 뿐만 아니라 모든 명령과 함께 작동 cat하지만 Linux 또는 Cygwin에서는 /dev/stdinstdin에서 열린 동일한 파일을 가리키며 어떤 경우에는 stdin과 정확히 동일하게 작동하지 않습니다.

그래서 당신은 이것을 할 수 있습니다 :

file=-
unset -v column pattern filepath
cmd=echo

while getopts f:c:e: opt; do
  case $opt in
    (f) file="$OPTARG";;
    (c) column="$OPTARG";;
    (e) pattern="$OPTARG";;
    (*) printf>&2 '%s\n' "Usage: $0 [-f file] [-c column] [-e pattern]"; exit 1
  esac
done
shift "$(( OPTIND - 1 ))"

cat -- "$file"

stdin()은 한 번만 읽을 수 있습니다 -.

또한 참고하십시오:

  • 오류는 stderr로 전송되어야 합니다.
  • echo$0임의의 데이터(예: 제어할 수 없는 데이터) 에는 사용할 수 없습니다 .
  • [...]동의한 대로 메시지를 사용하세요.임의로 선택할 수 있는, 따라서 의 경우 필수임을 -f [file]암시 하지만 해당 인수는 선택 사항이므로 여기서는 올바르지 않습니다.-f
  • path스크립트가 결국 해석될 가능성이 있는 경우 zsh( sh시뮬레이션이 아닌 경우) $path배열 변수가 / $PATH와 유사한 변수 이름을 지정하지 마십시오 .cshtcsh
  • 매개변수가 제공되었는지 확인하기 위해 null 테스트를 피해야 합니다. 예 -f ''를 들어, 대신 초기화 시 을 사용하여 변수가 설정되지 않았는지 확인하고 나중에도 여전히 설정되지 않았는지 확인하세요. 또는 추가 부울 플래그 변수를 사용하여 옵션이 통과되었는지 여부를 기록합니다.$file-funset -v var[ -z "${var+set}" ]
  • -사용자가 stdin이 아닌 현재 작업 디렉터리에서 호출 된 실제 파일을 의미하는 파일을 전달할 수 있도록 하려면 이를 핸들로 변환할 수 있습니다.-./-(f)
  • file=$(cat)stdin에서 읽을 수 있는 내용을 읽고 이를 file변수(메모리 내)에 저장합니다. 따라서 다른 사람들이 말했듯이 변수 이름은 얻는 입력 파일의 내용이기 때문에 약간 오해의 소지가 있습니다. 하지만 그것은 또한으깨다당신이 얻는 것은 $(...)NUL 문자를 제거하거나 차단하는 zsh를 제외하고 모든 후행 개행 문자를 제거한 것입니다. echo그것을 (임의의 데이터가 아닌) 사용한다면 스스로 echo피해를 입게 될 것입니다.

여기서는 반대 접근 방식을 취하고 -fstdin에 인수로 전달된 파일을 열 수도 있습니다.

unset -v column pattern filepath
cmd=echo

while getopts f:c:e: opt; do
  case $opt in
    (f) exec < "$OPTARG";;
    (c) column="$OPTARG";;
    (e) pattern="$OPTARG";;
    (*) printf>&2 '%s\n' "Usage: $0 [-f file] [-c column] [-e pattern]"; exit 1
  esac
done
shift "$(( OPTIND - 1 ))"

cat

exec파일을 열 수 없으면 POSIX 쉘이 자동으로 종료됩니다. -f할당할 때와 같이 여러 옵션이 전달된 경우 $file마지막 옵션만 고려됩니다.

답변2

실제 질문에 답하려면 test. 그래서

if [ -z "$file" ] ; then
    echo no file specified
elif [ -f "$file" ] ; then
    echo given a valid file "$file"
else
    echo Given "$file" but it is not a file
fi

그러나 나는 이것이 요점을 놓치고 있다고 생각합니다. file=$(cat)당신은 변수 이름의 재사용에 대해 혼란스러워하고 있다고 생각합니다 file. 그렇게 생각하면 file_contents=$(cat)상황이 더 명확해질 것이라고 생각합니다.

관련 정보