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