tsvmove (2084B)
1 #!/bin/sh 2 # vim: set ft=bash: 3 # tsvmove - Move a line in 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 10 usage() 11 { 12 cat <<EOT 13 Usage: ${0##*/} tsvfile.tsv [rowno | colno text] rowno 14 EOT 15 } 16 17 error() 18 { 19 printf "%s: %s\n" "${0##*/}" "$@" >&2 20 } 21 22 case $# in 23 3) inputfile=$1 24 linenofrom=$2 25 linenoto=$3 26 ;; 27 4) inputfile=$1 28 colnofrom=$2 29 searchtextfrom=$3 30 linenoto=$4 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 42 [ -w "${inputfile}" ] || { error "\`${inputfile}' not writeable"; exit 1; } 43 44 cp "${inputfile}" "$tmpf" 45 # shellcheck disable=SC2064 46 trap "rm -f \"$tmpf\"" HUP PIPE INT QUIT TERM EXIT 47 48 if [ -z "${linenofrom}" ]; then 49 linenofrom=$(cut -d"$tab" -f"${colnofrom}" "${inputfile}" | 50 grep -ni "${searchtextfrom}" | 51 sed 's/^\([0-9]\+\).*/\1/;1q') 52 # shellcheck disable=SC2140 53 [ -z "$linenofrom" ] && 54 { error "not found \`${searchtextfrom}' in column "\ 55 "${colnofrom}" 56 exit 1; } 57 fi 58 59 numlines=$(wc -l -- "${inputfile}" | awk '{print $1}') 60 if [ "${linenofrom}" -gt "${numlines}" ]; then 61 error "line number out of range: ${linenofrom}" 62 exit 1 63 elif [ "${linenoto}" -gt "${numlines}" ]; then 64 error "line number out of range: ${linenoto}" 65 exit 1 66 fi 67 68 if [ "${linenofrom}" -lt "${linenoto}" ]; then 69 delta=$((linenoto - linenofrom)) 70 { head -n$((linenofrom-1)) "${inputfile}" 71 tail +$((linenofrom+1)) "${inputfile}" | 72 head -n"${delta}" 73 head -n$((linenofrom)) "${inputfile}" | 74 tail -n1 75 tail +$((linenoto+1)) "${inputfile}"; } > "$tmpf" 76 mv "$tmpf" "${inputfile}" 77 elif [ "${linenofrom}" -gt "${linenoto}" ]; then 78 delta=$((linenofrom - linenoto)) 79 { head -n$((linenoto-1)) "${inputfile}" 80 head -n$((linenofrom)) "${inputfile}" | 81 tail -n1 82 tail +$((linenoto)) "${inputfile}" | 83 head -n"${delta}" 84 tail +$((linenofrom+1)) "${inputfile}"; } > "$tmpf" 85 mv "$tmpf" "${inputfile}" 86 fi