tsvedit (2103B)
1 #!/bin/sh 2 # vim: set ft=bash: 3 # tsvedit - Edit a line from a TSV file 4 # This program is licensed under the terms of GNU GPL v3 or (at your option) 5 # any later version. Copyright (C) 2023-2026 Страхиња Радић. 6 # See the file LICENSE for exact copyright and license details. 7 8 tab=$(printf "\t") 9 nl=' 10 ' 11 12 usage() 13 { 14 cat <<EOT 15 Usage: ${0##*/} tsvfile.tsv [rowno | colno text] 16 EOT 17 } 18 19 error() 20 { 21 printf "%s: %s\n" "${0##*/}" "$@" >&2 22 } 23 24 case $# in 25 2) inputfile=$1 26 lineno=$2 27 ;; 28 3) inputfile=$1 29 colno=$2 30 searchtext=$3 31 ;; 32 *) usage 33 exit 1 34 ;; 35 esac 36 37 if [ -L $inputfile ]; then 38 inputfile=$(readlink -f $inputfile) 39 fi 40 tmpf=${inputfile}~ 41 [ -w "${inputfile}" ] || { error "\`${inputfile}' not writeable"; exit 1; } 42 numlines=$(awk 'END {print NR}' "${inputfile}") 43 44 # shellcheck disable=SC2086 45 if [ ! $lineno ]; then 46 lineno=$(cut -d"$tab" -f"${colno}" -- "${inputfile}" | 47 grep -n "${searchtext}" | sed 's/^\([0-9]\+\).*/\1/;1q') 48 # shellcheck disable=SC2086 49 [ ! $lineno ] && 50 { error "not found \`${searchtext}' in column ${colno}" 51 exit 1; } 52 fi 53 54 savelineno="${lineno}" 55 # shellcheck disable=SC2030,SC2086 56 (while [ $lineno ]; do 57 case $(printf "%s\n" "${lineno}" | cut -c 1) in 58 [0-9]) ;; 59 *) error "argument not a number: \`${savelineno}'" 60 exit 1 61 ;; 62 esac 63 # shellcheck disable=SC2030 64 lineno=$(printf "%s\n" "${lineno}" | cut -c 2-) 65 done) || exit 1 66 67 # shellcheck disable=SC2031 68 if [ "${lineno}" -gt "${numlines}" ]; then 69 error "line number ${lineno} greater than the number of lines, \ 70 ${numlines}" 71 exit 1 72 fi 73 74 # shellcheck disable=SC2031 75 if [ "${lineno}" -lt 1 ]; then 76 error "line number must be positive: \`${lineno}'" 77 exit 1 78 fi 79 80 touch -- "$tmpf" 81 # shellcheck disable=SC2064 82 trap "rm -f \"$tmpf\"" HUP PIPE INT QUIT TERM EXIT 83 84 # shellcheck disable=SC2031 85 { head -n$((lineno-1)) -- "${inputfile}" 86 # shellcheck disable=SC1003 87 sed '/^#/d;s/\([^'"$tab"']*\)$/\1'"$tab"'/g' | tr -d '\n' | 88 sed 's/'"$tab"'$/\'"$nl"'/g' 89 tail +$((lineno+1)) -- "${inputfile}"; } > "$tmpf" 90 91 if diff "$tmpf" "${inputfile}" >/dev/null 2>&1; then 92 rm "$tmpf" 93 else 94 mv "$tmpf" "${inputfile}" 95 fi