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