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