I have a file with multiple lines, all in the same format. For each line, I need to replace the sequence of digits after the last : with a new value, but keep the single quote at the end of the line.
? How and where do the 4.5.6.7 come into play?
And, why does
replace 1.2.3.17 ?
If you got a single value to replace portions of the input line, sed might do. If there's more to be done, advanced tools like awk or perl might be the better choice.
Thanks!
Slight modification to the original problem:
So previously I wanted to replace the last digit before the single quote at end of line with a new value, but now I want to only do it based on the previous digits and a matching pattern.
If any(part of) line in file matches a certain pattern, replace the value after the last dot (and keep the single quote at end of line-same as before) with the value in pattern.
Can I do this using sed?
example:
Pattern to match=name1: 1.2.300.Y (or could be name1: 1.300.Y , so Y can be any number, I don't care what it is at this point).
All lines will be in the same format and ideally there will only be one line containing 'name1'.
So only the first line was a match and updated, 'X' was replaced with 'Y'. Line 4 wasn't changed( name2)
Pattern I'm looking for:
name1:1.2.300.Y
In other words:
{string}:{ a combination of one or more numbers and dots, not always 2 dots, but grouped together}.{one or more digits}
Or if I could also extract each field above from the original file into variables:
Var1=name1
Var2=1.2.300
Var3=Y
If it helps, my pattern-to-look-for could also be:
info:200/text/name1:1.2.300.Y
Instead of just:
name1:1.2.300.Y
I hope I explained it well, sorry if I might have over done it!
Thanks!!
---------- Post updated at 10:49 PM ---------- Previous update was at 10:48 PM ----------
Yes that works, thank you!
Slight modification to original problem:
previously I wanted to replace the last digit before the single quote at end of line with a new value, but now I want to only do it based on the previous digits and a matching pattern.
If any(part of) line in file matches a certain pattern, replace the value after the last dot (and keep the single quote at end of line-same as before) with the value in pattern.
Can I do this using sed?
example:
Pattern to match= name1:1.2.300.Y (or could be name1:1.300.Y, so Y can be any number, I don't care what it is at this point).
All lines will be in the same format and ideally there will only be one line containing 'name1'.
You best have two strings, one is the search pattern and one is the replacement value.
#!/bin/sh
pattern=$1
newval=$2
if [ $# -ne 2 ]; then
echo "usage: $0 'RE pattern' newval"
exit 1
fi
sed 's/\(.*'"$pattern"'\.\)[0-9]\{1,\}/\1'"$newval"'/' file
Here the given pattern must reach to the last . (before the last number). For example you can run your script with ./scriptname 'name1:1\.2\.300' 199 or ./scriptname ':1\.2\.300' 199 but not ./scriptname 'name1:1\.2\.' 199 .
The following modification searches the pattern in the whole line:
sed '/'"$pattern"'/ s/\(.*\.\)[0-9]\{1,\}/\1'"$newval"'/' file
This requires you to end the given pattern with a \. (otherwise there is a risk you match the first part of the number).
As an alternative you can put the trailing \. into the sed code
sed '/'"$pattern"\.'/ s/\(.*\.\)[0-9]\{1,\}/\1'"$newval"'/' file
I am confused also because my script proposal was for an input file where a number is to be substituted, as you specified in your post#1.
Now it has become a letter.?
@MadeInGermany:
the solution you provided with pattern/newval works perfectly fine.
I can modify "pattern" to be any portion of the string in each line, and the last digit will be replaced.
THe only change right now is I want to get the "pattern" and "newval" parameters required to do the sed by parsing a third variable, instead of defining them explicitly. The main problem seems to be with evaluating the vars.
Right now if I specify everything on the command line it works:
pattern='info:200\/text\/name1:1.2.300'
-->(im escaping the / and im definning it in single quotes )
newval=8
echo " $pattern "
-> info:200\/text\/name1:1.2.300
echo " $newval "
--> 8
and call sed:
sed '/'"$pattern"\.'/ s/\(.*\.\)[0-9]\{1,\}/\1'"$newval"'/' file
input (from file):
person1_desc: 'info:200/text/name1:1.2.300.X'
output:
person1_desc: 'info:200/text/name1:1.2.300.8'
This is great. So now I will try to get the values from a new variable called $input_line
input_line=info:200/text/name1:1.2.300.8
parse it:
pattern_2=$( echo $input_line | sed 's/\.[^.]*$//' )
--> info:200/text/name1:1.2.300
newval_2=$( echo $input_line | sed 's/.*\.//' )
--> 8
echo " $pattern_2 "
--> info:200/text/name1:1.2.300
echo "$newval_2 "
--> 8
so now if I call the exact same sed command, it doesnt work:
sed '/'"$pattern"\.'/ s/\(.*\.\)[0-9]\{1,\}/\1'"$newval"'/' file
I get:
sed: -e expression #1, char 33: extra characters after command
so thats why I want to
escape the slash in $pattern_2
not sure if I need to put $pattern_2 in single quotes?
I am still a bit confused: when you say .X you seem to mean that X is a number...
The / has no special meaning in an RE (=regular expression). But my sed scripts used the / delimiter. The following is with a different delimiter, #
sed '\#'"$pattern"\.'# s#\(.*\.\)[0-9]\{1,\}#\1'"$newval"'#' file
Perhaps the following is a little more precise, because it requires the search pattern to be placed left from the replacement area.
sed 's#\('"$pattern"'.*\.\)[0-9]\{1,\}#\1'"$newval"'#' file
Now you do not need to escape the / in the search pattern (instead need to escape a # ).
But you *must* escape the . character! In a RE it matches any character. For example pattern="2.0/text" would find 200/text . But pattern="2\.0/text" only finds 2.0/text .
--
You want to split the string at the last dot. You can use shell-builtins for that
# sed 's/[^:]*.$/whatever'"'"'/g' mytst
Name: 'text1:200/text2:whatever'
Name2: 'text3:200/text3:whatever'
# sed 's/[^.]*.$/whatever'"'"'/g' mytst
Name: 'text1:200/text2:1.2.3.whatever'
Name2: 'text3:200/text3:1.2.3.whatever'
@Beginner101
Note :
a) sometimes it's easier for people to understand what you need when you provide a well-chosen example of input and output file, rather than long explainations... :o
b) the dot before the dollar signe is useless here, but i leave it just to keep in mind that this last char matched (which is here a simple quote), is a little special and need therefore a special threatment.
---------- Post updated at 16:29 ---------- Previous update was at 13:02 ----------
Yep this is due to the fact that your pattern contains some / which get parsed.
In order to avoir tedious "escaping escape" gym ... you may want to give a try using ! as reference character in the s!pattern1!pattern2! expression rather than / so that the slash will be taken as litteral.