0
data.txt file : 
Roll no : 65 
Name    : Abc
Roll no : 67 
Name    : Pqr
Roll no : 68 
Name    : Xyz

Now, I want to take Roll no as input from user and then replace the old name with new name

sed  -i -e 's/'$tmproll'/{'$tmpName';s/\n.*//;}' $filename
sed  -i -e 's/'$tmproll'/'$tmpName'/{N;s/\n.*//;}' $filename

Expected Result :

Enter the Roll no to modify : 65
Enter new Name for that Roll no  : Mno
Then data.txt file : 
Roll no : 65 
Name    : Mno
Roll no : 67 
Name    : Pqr
Roll no : 68 
Name    : Xyz

My actual output

Enter the Roll no to modify : 65
Enter new Name for that Roll no  : Mno
sed: -e expression #1, char 17: unknown option to `s'
Luis Rico
  • 625
  • 6
  • 22
Shubham Pawar
  • 97
  • 2
  • 7

3 Answers3

1

As an alternative to using sed for in-place editing, you might consider ed, of all things (It's actually quite useful for simple editing of files in a script).

Demonstration script:

#!/bin/sh

tmproll=65
tmpname=Mno

ed -s data.txt <<EOF
/^Roll no[[:space:]]*:[[:space:]]*${tmproll}$/+1 s/:.*/: ${tmpname}/
w
EOF

It looks for a line matching the desired roll number (The leading /regex/), and on the line after it (+1), replaces everything after the colon with the new name (The s///). Then it saves the file (w).

Example:

$ cat data.txt
Roll no : 65 
Name    : Abc
Roll no : 67 
Name    : Pqr
Roll no : 68 
Name    : Xyz
$ sh example.sh
$ cat data.txt
Roll no : 65 
Name    : Mno
Roll no : 67 
Name    : Pqr
Roll no : 68 
Name    : Xyz
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • OK, will let you know – Shubham Pawar Jul 26 '19 at 12:32
  • I tried your code @shawn but whenever i copied it and paste it into vs code it gave me error – Shubham Pawar Jul 26 '19 at 13:19
  • @ShubhamPawar Your *editor* is giving an error when you try pasting into it? – Shawn Jul 26 '19 at 15:44
  • 'modify.sh: line 36: warning: here-document at line 6 delimited by end-of-file (wanted `EOF/^Roll') modify.sh: line 6: ed: command not found ' – Shubham Pawar Jul 27 '19 at 02:44
  • @ShubhamPawar Those are errors from `/bin/sh`, nothing to do with vscode or any other editor. You left out some lines from the above script for the first one, and the second one is self-explanatory but surprising. ed is in POSIX... what unixish OS doesn't include it as part of a base installation? – Shawn Jul 27 '19 at 08:43
  • I'm actual not working not unix/linux based os. I'm working on windows with *GIT Bash* – Shubham Pawar Jul 28 '19 at 13:47
0

This looks like you erroneously put an s before the first slash. s/regex/replacement/ replaces matches of regex with the text replacement, whereas just /regex/ is an address expression which selects lines which match regex.

You also put the replacement in a weird place, but your second attempt looks fixable with fairly minor changes. Try

sed  -i -e '/'"$tmproll"'/{N;s/\n.*/\nName: '"$tmpName"'/;}' "$filename"

Notice also the quoting fixes; see also When to wrap quotes around a shell variable? (the quoting could actually be simplified quite a bit by switching to double quotes altogether).

In more detail, a sed script consists of a sequence of address command pairs. The address is optional; in its absence, the command is applied to every input line. This script contains the commands N (fetch the next input line, so that the pattern space contains both the original line and the following one, separated by a newline character) and s/regex/replacement/ to replace the text after the newline character (i.e. the new line we fetched with N) with new text. The commands are inside braces to say they all should be applied if the address expression matched.

Using sed for any non-trivial logic tends to produce write-only scripts; this would arguably be easier to write and understand in Awk.

awk -v no="$tmproll" -v name="$tmpName" '/Roll no / && $4 == no { replace=1 }
    /Name / && replace { $3=name }1' "$filename"

You will need to write the result to a temporary file and then rename it if you don't have GNU Awk, which has an inplace facility similar to sed -i.

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

I don't think that it the right way to do this but I have come up with a solution. So first we'll try to find the line number of the Roll no in the file,then wel'll increment it by one,since our Name comes after Roll no. Then we'll replace that line with the desired Name that we want. Here's the code for it :

Data.txt before modification 
Roll no : 65 
Name    : ABC
Roll no : 66 
Name    : DEF
Roll no : 67 
Name    : MNO

#CODE STARTS FROM HERE

echo -n "Enter the Roll no to modify : " 
read tmproll 
if grep -q $tmproll "$filename"; then 
lineno=$(sed  -n -e '/'$tmproll'/=' $filename)
lineno=$((lineno+1));
echo -n "Enter the new Name : "
read tmpName
sed -i -e "$lineno c\Name    : $tmpName" $filename
fi 

#CODE ENDS HERE

Data.txt after this code 
Roll no : 65 
Name    : ABC
Roll no : 66 
Name    : DEF
Roll no : 67 
Name    : PQR
Shubham Pawar
  • 97
  • 2
  • 7