파일을 편집하기 위한 awk 명령을 만드는 bash 스크립트가 작동하지 않습니다.

파일을 편집하기 위한 awk 명령을 만드는 bash 스크립트가 작동하지 않습니다.

i 플래그가 명령에 추가되었는지 확인하고 추가된 경우 stdin에서 파일에 쓰는 다음 if-else 문이 있습니다.

 29 if [ $inplace -eq 1 ]; then
 30    tmp_file=$(mktemp)
 31    awk -v num="^$number" -v col="$column" -v value="$value" -F ',' \
 32       'BEGIN{OFS=FS}{ if ($0 ~ num) { $col=value; print } else print}' "$file" > "$tmp_file"
 33    mv "$tmp_file" "$file"
 34 else
 35    awk -v num="^$number" -v col="$column" -v value="$value" -F ',' \
 36       'BEGIN{OFS=FS}{ if ($0 ~ num) { $col=value; print } else print}' "$file"
 37 fi

하지만 다음과 같은 오류가 발생합니다.

mv: cannot move '/tmp/tmp.ahALZC2Hgh' to '': No such file or directory

이는 $file이 비어 있음을 의미합니다. stdin은 한 번만 사용할 수 있고 위의 awk cmd에서 사용된다는 내용을 어딘가에서 읽었기 때문에 의미가 있습니다.

가치를 보존하는 방법을 아는 사람이 있습니까? (다음과 같은 작업을 수행하지 않는 경우: var=$(cat) 나쁜 습관이라고 들었기 때문인가요?)

또는 구현해서는 안 되기 때문에 나쁜 생각이라면 그것도 괜찮습니다!

파일을 실행하고 오류가 발생하는 명령은 다음과 같습니다.

cat data.csv | ./update.sh -n 444 -c 2 -v "Alex" -i

i 플래그는 사용자가 원본 파일을 변경하고 싶다는 것을 나타내기 위해 사용됩니다. 이 경우 $inplace 변수는 다음과 같은 경우 while 루프에서 1로 설정됩니다.

  3 while getopts f:n:c:v:i opt; do
  4     case $opt in
  5       f) file="$OPTARG";;
  6       n) number="$OPTARG";;
  7       c) column="$OPTARG";;
  8       v) value="$OPTARG";;
  9       i) inplace=1;;
 10       *) printf>&2 '%s\n' "Usage: $0 [-f file] [-n number] [-c column] [-v value]";;
 11     esac
 12 done

전체 스크립트는 다음과 같습니다.

#!/bin/bash

while getopts f:n:c:v:i opt; do
    case $opt in
      f) file="$OPTARG";;
      n) number="$OPTARG";;
      c) column="$OPTARG";;
      v) value="$OPTARG";;
      i) inplace=1;;
      *) printf>&2 '%s\n' "Usage: $0 [-f file] [-n number] [-c column] [-v value]";;
    esac
done


if [ -z "$column" ]; then
   echo "Please specify a column number with -c." >&2
   exit 1
elif [ -z "$number" ]; then
   echo "Please specify a phone number to filter by via -n" >&2
   exit 1
elif [ -z "$value" ]; then
   echo "Please specify the new value via -v" >&2
   exit 1
elif [ "$column" -gt 4 ] || [ "$column" -lt 1 ]; then
       echo "this script can only handle cols1-4. for group editing, try ./groups.sh" >&2
       exit 1
fi    

if [ $inplace -eq 1 ]; then  
   tmp_file=$(mktemp) 
   awk -v num="^$number" -v col="$column" -v value="$value" -F ',' \
      'BEGIN{OFS=FS}{ if ($0 ~ num) { $col=value; print } else print}' "$file" > "$tmp_file"
   mv "$tmp_file" "$file"
else
   awk -v num="^$number" -v col="$column" -v value="$value" -F ',' \
      'BEGIN{OFS=FS}{ if ($0 ~ num) { $col=value; print } else print}' "$file"
fi


exit 0

답변1

  • "따라서 이 경우 간단한 -i filename선택이 최선의 선택이 될 것입니다"라는 귀하의 진술과 관련하여 - 아니요, 최선의 선택은 사용자가 하는 것이지 cat foo | command > filename가 아닙니다 cat foo | command -i filename.
  • 표준 입력에 대한 "내부" 편집은 없으며 표준 출력을 파일로 지정하면 > filename이미 완료되었습니다.
  • -i 옵션에는 파일 이름 인수가 포함되어서는 안 됩니다. 이는 의미가 없으며 코드를 복잡하게 만듭니다. 입력 파일이 없고 누군가가 -i를 사용하여 스크립트를 호출하면 sed와 마찬가지로 오류로 보고됩니다. 예를 들어 시도해 보면 seq 3 | sed -i 's/2/4/'알려줄 것입니다.sed: no input files
  • 작성된 대로 awk에 오류가 발생하면 코드는 입력 파일을 삭제합니다. 사용:
> "$tmp_file" &&
mv "$tmp_file" "$file"

바꾸다:

> "$tmp_file"
mv "$tmp_file" "$file"
  • { if ($0 ~ num) { $col=value; print } else print }=는 { if ($0 ~ num) { $col=value } print }관용적으로 다음과 같이 쓸 수 있습니다 $0 ~ num { $col=value } 1.
  • 내가 다시 제공한 Shift 명령을 제거하여 나머지 코드를 다시 작성하기 어렵게 만들었습니다.
  • -f file 옵션이 있어서는 안 됩니다. 입력으로 사용하려는 모든 파일은 getopts 루프에서 처리되는 옵션+인수 뒤에 있어야 하며 "$@"로 주소가 지정되어야 합니다.
  • 또한보십시오기타 제안너는 받았다.

다음을 시작점으로 사용해 보세요(테스트되지 않음).

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

tmp_file=$(mktemp) || exit 1
trap 'rm -f "$tmp_file"; exit' EXIT

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

if [[ -z "$column" ]]; then
   echo "Please specify a column number with -c." >&2
   exit 1
elif [[ -z "$number" ]]; then
   echo "Please specify a phone number to filter by via -n" >&2
   exit 1
elif [[ -z "$value" ]]; then
   echo "Please specify the new value via -v" >&2
   exit 1
elif ! (( 1 <= column )) && (( column <= 4 )); then
   echo "this script can only handle cols1-4. for group editing, try ./groups.sh" >&2
   exit 1
fi

xform() {
   awk -v num="^$number" -v col="$column" -v value="$value" \
      'BEGIN{FS=OFS=","} $0 ~ num{$col=value} 1' "$@"
}

if [[ -n "$inplace" ]]; then
   if (( $# == 0 )); then
      echo "cannot do inplace editing as requested by -i without an input file present" >&2
      exit 1
   fi
   all_writeable=1
   for file; do
       if [[ ! -w "$file" ]]; then
          echo "file \"$file\" is not writeable" >&2
          all_writeable=0
       fi
   done
   if (( all_writeable == 0 )); then
       exit 1
   fi
   for file; do
       xform "$file" > "$tmp_file" &&
       mv "$tmp_file" "$file"
   done
else
   xform "$@"
fi

column자연수처럼 기대하는 값이 실제로 자연수인지 확인하려면 옵션 매개변수에 대해 추가 검증을 수행해야 합니다.

관련 정보