Skip to main content
added 1275 characters in body
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60
  • Regarding your statement "so in this case a simple -i filename would be the best option as" - no, the best option is for the user to do cat foo | command > filename, not cat foo | command -i filename.
  • There is no "inplace" editing of stdin, you're just directing stdout to a file and that's what > filename already does.
  • Your -i option should not have a file name argument, that wouldn't make sense and would complicate your code. If there's no input file and someone calls your script with -i then report that as an error, just like sed does, e.g. try seq 3 | sed -i 's/2/4/' and it'll tell you sed: no input files
  • As written your code would trash your input file if awk encountered a failure. Use:
> "$tmp_file" && mv "$tmp_file" "$file" 

See the comments you received and then tryinstead of:

> "$tmp_file" mv "$tmp_file" "$file" 
  • { if ($0 ~ num) { $col=value; print } else print } = { if ($0 ~ num) { $col=value } print } which can be written idiomatically as just $0 ~ num { $col=value } 1.
  • You've removed the shift command I had provided again, thereby making the rest of your code harder to write again.
  • You should not have a -f file option, any file(s) you want to use as input should just come after the options+arguments being processed in your getopts loop and be addresses by "$@".
  • See also the other comments you received.

Try this (untested) as a starting point:

See the comments you received and then try this (untested) as a starting point:

  • Regarding your statement "so in this case a simple -i filename would be the best option as" - no, the best option is for the user to do cat foo | command > filename, not cat foo | command -i filename.
  • There is no "inplace" editing of stdin, you're just directing stdout to a file and that's what > filename already does.
  • Your -i option should not have a file name argument, that wouldn't make sense and would complicate your code. If there's no input file and someone calls your script with -i then report that as an error, just like sed does, e.g. try seq 3 | sed -i 's/2/4/' and it'll tell you sed: no input files
  • As written your code would trash your input file if awk encountered a failure. Use:
> "$tmp_file" && mv "$tmp_file" "$file" 

instead of:

> "$tmp_file" mv "$tmp_file" "$file" 
  • { if ($0 ~ num) { $col=value; print } else print } = { if ($0 ~ num) { $col=value } print } which can be written idiomatically as just $0 ~ num { $col=value } 1.
  • You've removed the shift command I had provided again, thereby making the rest of your code harder to write again.
  • You should not have a -f file option, any file(s) you want to use as input should just come after the options+arguments being processed in your getopts loop and be addresses by "$@".
  • See also the other comments you received.

Try this (untested) as a starting point:

added 274 characters in body
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60

See the comments you received and then try this (untested) as a starting point:

$ 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 

You should do more validation on the option arguments to ensure, for example, that the values like column that you expect to be a natural number truly are natural numbers.

See the comments you received and then try this (untested) as a starting point:

$ 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 for file; do xform "$file" > "$tmp_file" && mv "$tmp_file" "$file" done else xform "$@" fi 

You should do more validation on the option arguments to ensure, for example, that the values like column that you expect to be a natural number truly are natural numbers.

See the comments you received and then try this (untested) as a starting point:

$ 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 

You should do more validation on the option arguments to ensure, for example, that the values like column that you expect to be a natural number truly are natural numbers.

`]` s/b `]]` to match keyword `[[`, my bash complains.
Source Link
jthill
  • 2.8k
  • 14
  • 16

See the comments you received and then try this (untested) as a starting point:

$ 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 for file; do xform "$file" > "$tmp_file" && mv "$tmp_file" "$file" done else xform "$@" fi 

You should do more validation on the option arguments to ensure, for example, that the values like column that you expect to be a natural number truly are natural numbers.

See the comments you received and then try this (untested) as a starting point:

$ 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 for file; do xform "$file" > "$tmp_file" && mv "$tmp_file" "$file" done else xform "$@" fi 

You should do more validation on the option arguments to ensure, for example, that the values like column that you expect to be a natural number truly are natural numbers.

See the comments you received and then try this (untested) as a starting point:

$ 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 for file; do xform "$file" > "$tmp_file" && mv "$tmp_file" "$file" done else xform "$@" fi 

You should do more validation on the option arguments to ensure, for example, that the values like column that you expect to be a natural number truly are natural numbers.

added 169 characters in body
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60
Loading
Source Link
Ed Morton
  • 35.9k
  • 6
  • 25
  • 60
Loading