Create a file a.tsv with two lines
echo aa bbb ccc ddd >a.tsv
echo xxxxxxxaa bbb ccc ddd >>a.tsv
replace each line with dynamic generated string in a shell script a.sh
#!/bin/bash
#get line number
l1=$1
l2=$(expr $1 1)
#input file name
fn=$2
#get string in l1 line
vv="{${l1},${l1}p;${l2}q}"
v1=$(sed -n ${vv} $fn )
echo $v1
#cut off 6 chars from the end of string v1
v2=${v1::-6}
echo $v2
#replace l1 line v1 with new line v2
vb="{s|${v1}|${v2}|g }"
echo $vb
sed -i -r '$vb' $fn
when I run it as:
./a.sh 1 a.tsv
But I get those output:
What is wrong?
aa bbb ccc ddd
aa bbb c
{s|aa bbb ccc ddd|aa bbb c|g }
sed: -e expression #1, char 3: expected newer version of sed
CodePudding user response:
The output of echo aa bbb ccc ddd >a.tsv is not a TSV (Tab-Separated Values) so don't name it a.tsv as that's misleading, use a.txt if you want it to have a suffix.
You can't easily do what you're trying to do robustly using sed since sed doesn't understand literal strings, see is-it-possible-to-escape-regex-metacharacters-reliably-with-sed. You should use a tool that does have literal string functions such as awk instead.
If I understand your code correctly it seems like this is what you're trying to do:
$ cat a.txt
aa bbb ccc ddd
xxxxxxxaa bbb ccc ddd
$ cat a.sh
#!/usr/bin/env bash
awk -i inplace -v lineNr="$1" '
NR == lineNr {
$0 = substr($0,1,length()-6)
}
{ print }
' "$2"
$ ./a.sh 1 a.txt
$ cat a.txt
aa bbb c
xxxxxxxaa bbb ccc ddd
The above is using GNU awk for -i inplace, just like you were using GNU sed for -i (and -r), but unlike a sed solution, it'll work for any characters in the input.
