ファイルを編集するための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自然数のように期待する値が実際に自然数であることを確認するには、オプションパラメータに対して追加の検証を実行する必要があります。

関連情報