exchange two words using sed - sed

I am trying to exchange two words in a line but it doesn't work. For example: "Today is my first day of university" should be "my is Today first day of university"
This is what I tried:
sed 's/\([a-zA-z0-9]*\)\([a-zA-z0-9]*\)\([a-zA-z0-9]*\)/\3\2\1/' filename.txt
What am I doing wrong?

I start to make it with \s which means any whitespaces chars.
I use it for match every words with [^\s]*which match with everything but not spaces.
And I had \s* for match withspaces between words. And don't forget to rewrite a space in replacement.
Look a this for an example:
sed 's#\([^ ]*\)\s+#\1 #'
( I use # instead of /)

sed -r 's/^(\w+)(\s+\w+\s+)(\w+)(.*)/\3\2\1\4/'
with your example:
kent$ echo "Today is my first day of university"|sed -r 's/^(\w+)(\s+\w+\s+)(\w+)(.*)/\3\2\1\4/'
my is Today first day of university
for your problem, awk is more straightforward:
awk '{t=$1;$1=$3;$3=t}1'
same input:
kent$ echo "Today is my first day of university"|awk '{t=$1;$1=$3;$3=t}1'
my is Today first day of university

Try this:
sed -rn 's/(\w+\s)(\w+\s)(\w+\s)(.*)/\3\2\1\4/p' filename.txt
-n suppress automatic printing of pattern space
-r use extended regular expressions in the script
\s for whitespace

This might work for you (GNU sed):
sed -r 's/(\S+)\s+(\S+)\s+(\S+)/\3 \2 \1/' file

You are not accounting for whitespace.
use [ \t]+ between words.

Related

Substring file name in Unix using sed command

I want to substring the File name in unix using sed command.
File name : Test_Test1_Test2_10082019_030013.csv.20191008-075740
I want the characters after the 3rd underscore or (all the characters after Test2 ) i need to be printed .
Can this be done using sed command?
I have tried this command
sed 's/^.*_\([^_]*\)$/\1/' <<< 'Test_Test1_Test2_10082019_030013.csv.20191008-075740'
but this is giving result as 030013.csv.20191008-075740
I need it from 10082019_030013.csv.20191008-075740
Thanks
Neha
To remove from the beginning up to including the 3rd underscore you can use
sed 's/^\([^_]*_\)\{3\}//' <<< 'Test_Test1_Test2_10082019_030013.csv.20191008-075740'
This removes the initial part that consists of 3 groups of (any number of non-underscore characters followed by an underscore). The result is
10082019_030013.csv.20191008-075740
If you use GNU sed you can switch it to extended regular expressions and omit the backslashes.
sed -r 's/^([^_]*_){3}//' <<< 'Test_Test1_Test2_10082019_030013.csv.20191008-075740'
Could you please try following.
sed 's/\([^_]*\)_\([^_]*\)_\([^_]*\)_\(.*\)/\4/' Input_file
Or as per Bodo's nice suggestion:
sed 's/[^_]*_[^_]*_[^_]_\(.*\)/\1/' Input_file
This might work for you (GNU sed):
sed 's/_/\n/3;s/.*\n//;t;s/Test2/\n/;s/.*\n//;t;d' file
Replace the third _ by a newline and then remove everything upto and including the first newline. If this succeeds, bail out and print the result. Otherwise, try the same method with Test2 and if this fails delete the entire line.

how to define split patterns in sed using spaces

I am new to this forum and this is my first query, hope I am not duplicating stuff.
I need to replace the following strings in a C file and I am using Sed for this purpose.
Input:
#define N_MAX_ITEMS 20 // some comment
#define N_TOTAL_COUNT 10
Expected output:
N_MAX_ITEMS = 20
N_TOTAL_COUNT = 10
The inputs can have multiple or single spaces or tabs in between.
I am using the following sed command in MAKEfile, to be executed in Cygwin environment.
macros_$(HW_TYPE).ini: macros_temp.h
rm -f $#
sed -e "s/\(#define[ \t]*\) \(N_.*\) \([\s\t]*[A-Z0-9_(].*\)/\2=\3/" <$^ >>$#
but the output is not proper particularly if for the expression that have comments appended.
The generic idea is, that my sed should be able to select different words till the first space or tab encountered.
This might work for you (GNU sed):
sed -r 's/^#define\s+(\S+)\s+(\S+).*/\1 = \2/' file
Use the metacharacters \s and \S for whitespace and non-whitespace and the + metacharacter for one or more.

sed multiple pattern matches in a line

I'm trying to write a sed command to convert lines:
<http://dbpedia.org/resource/BoA> <http://dbpedia.org/ontology/wikiPageWikiLink> <http://dbpedia.org/resource/Ne-Yo> .
<http://dbpedia.org/resource/BoA> <http://dbpedia.org/ontology/wikiPageWikiLink> <http://dbpedia.org/resource/Tablo> .
to
BoA, Ne-Yo
BoA, Tablo
I know how to match and print using /(/) but I can't find a way to print two matches.
Using awk you can do:
awk -F"[/>]" '/http/ {print $5 ", " $15}' file
BoA, Ne-Yo
BoA, Tablo
Use parentheses and then \1 to print the first match, \2 to print the second match, and so on.
sed 's|<http://dbpedia.org/resource/\([^>]\+\)> <[^>]\+> <http://dbpedia.org/resource/\([^>]\+\)>.*|\1,\2|g' input.txt
A little verbose, though. Put your text into input.txt file.
Less verbose, but also less accurate than #rendon's solution:
sed -e 's?.*/resource/\([^>]*\)>.*/resource/\([^>]*\).*?\1, \2?' input.txt
If it's good enough then this is more readable.
This might work for you (GNU sed):
sed -r 's|[^>]*/([^>]*)>.*/([^>]*).*|\1, \2|' file

sed remove multiple characters surrounded by digits

I have a file with following contents:
EMAIL|TESTNUMBER|DATE
somemail#address.com|123456789|2011-02-08T16:36:02Z
How do I remove capital letters T between the date and time and Z at the end of the line using sed?
Thanks!
If the format is fixed and each line always matches T\d\d:\d\d:\d\dZ, then you could try the simple:
$ sed 's/T\(..:..:..\)Z$/ \1/'
(Untested)
Perhaps there's a fancier way, but the following script works for me:
s/\(....-..-..\)T\(.*\)/\1 \2/
s/Z$//
Example...in-bound file:
somemail#address.com|123456789|2011-02-08A16:36:02X
somemail#address.com|123456789|2011-02-08T16:36:02Z
somemail#address.com|123456789|2011-02-08B16:36:02Y
Output:
D:\>sed -f sedscr testfile
somemail#address.com|123456789|2011-02-08A16:36:02X
somemail#address.com|123456789|2011-02-08 16:36:02
somemail#address.com|123456789|2011-02-08B16:36:02Y
Cat it through:
sed 's/\([0-9]+\)T\([0-9]+\)/\1\2//' | sed 's/Z$//'
Edit
Oh my! I've just realized (thanks #Fredrik) that for a long time I wasted processes! Shame on me! Now I'm Church of The One Process convert. Here is the blessed version of the above abominated oneliner:
sed 's/\([0-9]+\)T\([0-9]+\)/\1\2//; s/Z$//' the_file.txt

sed: Replace part of a line

How can one replace a part of a line with sed?
The line
DBSERVERNAME xxx
should be replaced to:
DBSERVERNAME yyy
The value xxx can vary and there are two tabs between dbservername and the value. This name-value pair is one of many from a configuration file.
I tried with the following backreference:
echo "DBSERVERNAME xxx" | sed -rne 's/\(dbservername\)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'
and that resulted in an error: invalid reference \1 on `s' command's RHS.
Whats wrong with the expression? Using GNU sed.
This works:
sed -rne 's/(dbservername)\s+\w+/\1 yyy/gip'
(When you use the -r option, you don't have to escape the parens.)
Bit of explanation:
-r is extended regular expressions - makes a difference to how the regex is written.
-n does not print unless specified - sed prints by default otherwise,
-e means what follows it is an expression. Let's break the expression down:
s/// is the command for search-replace, and what's between the first pair is the regex to match, and the second pair the replacement,
gip, which follows the search replace command; g means global, i.e., every match instead of just the first will be replaced in a line; i is case-insensitivity; p means print when done (remember the -n flag from earlier!),
The brackets represent a match part, which will come up later. So dbservername is the first match part,
\s is whitespace, + means one or more (vs *, zero or more) occurrences,
\w is a word, that is any letter, digit or underscore,
\1 is a special expression for GNU sed that prints the first bracketed match in the accompanying search.
Others have already mentioned the escaping of parentheses, but why do you need a back reference at all, if the first part of the line is constant?
You could simply do
sed -e 's/dbservername.*$/dbservername yyy/g'
You're escaping your ( and ). I'm pretty sure you don't need to do that. Try:
sed -rne 's/(dbservername)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'
You shouldn't be escaping things when you use single quotes. ie.
echo "DBSERVERNAME xxx" | sed -rne 's/(dbservername[[:blank:]]+)([[:alpha:]]+)/\1 yyy/gip'
You shouldn't be escaping your parens. Try:
echo "DBSERVERNAME xxx" | sed -rne 's/(dbservername)[[:blank:]]+([[:alpha:]]+)/\1 yyy/gip'
This might work for you:
echo "DBSERVERNAME xxx" | sed 's/\S*$/yyy/'
DBSERVERNAME yyy
Try this
sed -re 's/DBSERVERNAME[ \t]*([^\S]+)/\yyy/ig' temp.txt
or this
awk '{if($1=="DBSERVERNAME") $2 ="YYY"} {print $0;}' temp.txt