Bash 스크립트/명령에서 누락된 입력 처리

Bash 스크립트/명령에서 누락된 입력 처리

head수정된 스크립트(명령?)를 ~/.bashrc에 추가하겠습니다 . 수동으로 입력하든, 와일드카드에서 파생하든, stdin에서 제공하든 입력을 예상대로 처리합니다. 그러나 에 인수를 제공하는 것을 잊어버리면 headj터미널이 중단되고 Ctrl-C를 사용하여 다시 시작할 수 없습니다.

echo다음은 내 코드입니다(디버깅 목적으로 일부 호출 포함).

headj(){
    echo "script makes it this far without arguments"
    IFS=" " read -r -a input <<< "${@:-$(</dev/stdin)}"
    echo "but but crashes before getting here"
    # 
    for i in ${input[@]}; do
        echo -e "███████████████████████████████████████████████████████████████████████████████"
        echo -e "headj $i start"
        head -50 "$i"
    done
}

다음과 같이 동작합니다:

$ headj list1
script makes it this far without arguments
but not this far
███████████████████████████████████████████████████████████████████████████████
headj list1 start
a
b

$ headj list*
script makes it this far without arguments
but not this far
███████████████████████████████████████████████████████████████████████████████
headj list1 start
a
b

███████████████████████████████████████████████████████████████████████████████
headj list2 start
c
d

$ ls -1 li* | headj
script makes it this far without arguments
but not this far
███████████████████████████████████████████████████████████████████████████████
headj list1 start
a
b

███████████████████████████████████████████████████████████████████████████████
headj list2 start
c
d

$ headj
script makes it this far without arguments

그것이 걸려있는 곳입니다.

읽기 입력을 사용해 보았 input=( ${@:-$(</dev/stdin)} )으나 동일한 오류가 발생했습니다. 오류를 처리하려면 스크립트 시작 부분에 이 코드를 추가하세요.

if [ -z ${*:+x} ]; then
    echo "headj requires at least one argument"
    return
fi

더 좋은 방법이 있나요? 또, 이런 질문에는 꼭 검색해야 할 키워드가 있나요?

답변1

인수나 잘못된 파이프 없이 실행하고 있고 함수의 stdin에 파일 이름을 쓰고 싶지 않다고 가정하면(그렇게 하는 이유) stdin이 tty인지 확인하는 검사를 추가하겠습니다.

headj() {
    local files=()
    if [ "$#" -gt 0 ]; then
        files=("$@")
    elif ! tty >/dev/null; then
        readarray -t files
    else
        echo "Will not read filenames from a tty!" >&2
    fi
    for file in "${files[@]}"; do
        echo "do something with $file..."
    done
}

따라서 이것은 작동합니다.

$ ls *.txt |headj
do something with test.txt...

그러나 이것은 다음에 대해 불평합니다.

$ headj
Will not read filenames from a tty!

사용하는 명령 은 read파일 이름을 공백으로 분할하므로 그렇게 하지 않을 것입니다. 따라서 매개변수 수와 위 배열의 조건이 달라집니다. 줄 바꿈 readarray으로 구분된 항목 목록을 읽어야 합니다. 이는 파이프로 연결될 lsfind생성되는 항목이지만, 물론 이는 줄 바꿈이 포함된 파일 이름이 작동하지 않음을 의미합니다.

(약간 까다로울 수도 있지만 "$@"매개변수 <<<나 작업에서는 여러 단어를 생성해야 하기 때문에 사용하지 않을 것입니다. 그러나 그런 경우에는 그렇게 하지 않습니다. 사용하면 <<< "$*"의도가 단일 문자열을 변환하는 것임을 더 명확하게 할 수 있습니다 . )

^C가 작동하지 않는 이유에 대해서는 반복할 수 없으며 함수가 그렇게 하도록 되어 있는 것 같지 않습니다.

답변2

방금 bashrc에 기능을 추가하는 방법을 배웠습니다. 고마워요. 문제를 해결하려면 이것을 시도해 보세요.

headj(){
  ARG=${1? Error. Please, provide the input file. Example: headj filename}
  #echo "script makes it this far without arguments"
  IFS=" " read -r -a input <<< "${@:-$(</dev/stdin)}"
  #echo "but but crashes before getting here"
  # 
  for i in ${input[@]}; do
    echo -e ""`enter code here`
    echo -e "headj $i start"
    head -50 "$i"
done}
$headj

배쉬: 1: 오류. 입력 파일을 제공해 주세요. 예: headj 파일 이름

파이프의 예

$echo "It works for me." > answer.txt
$ cat answer.txt

이것은 나에게 효과적입니다.

$headj  answer.txt  | awk '{print $_}'

headj 응답.txt 시작

이것은 나에게 효과적입니다.

headj  answer.txt  | awk '{print $_}' | sed 's/me./me. It should work for you too./g'

headj 응답.txt 시작

이것은 나에게 효과적입니다. 그것은 당신에게도 효과가 있을 것입니다.

관련 정보