LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   sed - using variable values as patterns (https://www.linuxquestions.org/questions/programming-9/sed-using-variable-values-as-patterns-925103/)

danielbmartin 01-22-2012 11:37 AM

sed - using variable values as patterns
 
This is purely a learning exercise.
I have no real-world application.

I have a file of names in the format FirstName LastName.
I want to exchange the two fields to produce a new file
containing the same information in the format LastName FirstName.

This works ...
Code:

sed 's/\([[:graph:]]*\) \([[:graph:]]*\)/\2 \1/'
As an experiment I tried to specify the patterns as variables.
Code:

Word=' \([[:graph:]]*\) '
sed 's/' $Word $Word '/\2 \1/'

This fails with ...
Quote:

sed: -e expression #1, char 2: unterminated `s' command
Please advise.

Daniel B. Martin

millgates 01-22-2012 12:01 PM

Quote:

Originally Posted by danielbmartin (Post 4581376)
Code:

Word=' \([[:graph:]]*\) '
sed 's/' $Word $Word '/\2 \1/'


There are spaces in the argument to sed, therefore sed recieves the expression as 4 separate arguments. You should remove the spaces or quote them or use double quotes:
Code:

sed 's/'$Word$Word'/\2 \1/'
sed 's/ '$Word' '$Word' /\2 \1/'
sed 's/'" $Word $Word "'/\2 \1/'

or something along those lines

danielbmartin 01-22-2012 07:52 PM

Quote:

Originally Posted by millgates (Post 4581401)
There are spaces in the argument to sed, therefore sed recieves the expression as 4 separate arguments. You should remove the spaces or quote them or use double quotes:
Code:

sed 's/'$Word$Word'/\2 \1/'
sed 's/ '$Word' '$Word' /\2 \1/'
sed 's/'" $Word $Word "'/\2 \1/'

or something along those lines

Thank you, millgates, for your timely and informative response. I removed the leading and trailing blanks from the variable Word.
Code:

Word='\([[:graph:]]*\)'
Having done this, all three of your sed examples work. However, the first of the three puts a leading blank on each line and I don't understand why that happens.

Daniel B. Martin

grail 01-23-2012 12:05 AM

How about just use double quotes:
Code:

sed "s/$Word$Word/\2 \1/"

danielbmartin 01-23-2012 10:23 AM

Whoa! I took a closer look at the suggested solutions and
they don't work (unlikely), or
I've implemented them incorrectly.

Here's some simple code. Try it yourself and tell me how I goofed it!

Code:

echo; echo The input file is...
cat < $InFile
 
echo; echo Example 1...
sed 's/\([[:graph:]]*\) \([[:graph:]]*\)/\2 \1/' $InFile

Word='\([[:graph:]]*\)'

echo; echo Example 2...
sed 's/'$Word$Word'/\2 \1/' $InFile

echo; echo Example 3...
sed 's/ '$Word' '$Word' /\2 \1/' $InFile
 
echo; echo Example 4...
sed 's/'" $Word $Word "'/\2 \1/' $InFile

echo; echo Example 5...
sed "s/$Word$Word/\2 \1/" $InFile 
echo; echo

Here is the output from running that code.
Code:

The input file is...
Charles Curtis
John Garner
Henry Wallace
Alben Barkley

Example 1...
Curtis Charles
Garner John
Wallace Henry
Barkley Alben

Example 2...
 Charles Curtis
 John Garner
 Henry Wallace
 Alben Barkley

Example 3...
Charles Curtis
John Garner
Henry Wallace
Alben Barkley

Example 4...
Charles Curtis
John Garner
Henry Wallace
Alben Barkley

Example 5...
 Charles Curtis
 John Garner
 Henry Wallace
 Alben Barkley

Daniel B. Martin

firstfire 01-23-2012 10:46 AM

Hi.

5th example should look like this
Code:

$ Word='\([[:graph:]]*\)'
$ echo a b | sed "s/$Word $Word/\2 \1/"
b a

Note the space between two $Word's. Without the space you would get
Code:

$ echo a b | sed "s/$Word$Word/[\2] {\1}/"
[] {a} b

Space do not belong to the [:graph:] character class, so the first group matches only `a' and the second one matches empty string. IMO using double quotes (") is a preferred way to do such task.

jthill 01-23-2012 11:08 AM

You might find the following program helpful:
Code:


~/sandbox/49381$ cat >showargs.c
#include <stdio.h>
void main (int c, char **v, char **e)
{
        while (*v) puts(*v++);
        while (*e) puts(*e++);
}
~/sandbox/49381$ make showargs
cc    showargs.c  -o showargs
~/sandbox/49381$ ./showargs *
./showargs
UIDvsSID
a
a.cc
b
b.cc
declorder.cc
duff.cc
duff.o
opendir
opendir.cc
opendir2
opendir2.cc
sanitize
showargs
showargs.c
size
size.c
tags
SHELL=/bin/bash
TERM=xterm
XDG_SESSION_COOKIE=03b561d92e2a1484d958eade00000009-1327249405.440338-1264992931
TMPDIR=/tmp/jthill
WINDOWID=6291469
HUSHLOGIN=FALSE
XTERM_SHELL=/bin/bash
USER=jthill
  (and the rest of the environment variables...)

and you can pipe the result through 'sed -n l' or 'cat -A' if spacing or the like is a concern.

danielbmartin 01-23-2012 02:20 PM

Quote:

Originally Posted by firstfire (Post 4582248)
5th example should look like this
Code:

$ Word='\([[:graph:]]*\)'
$ echo a b | sed "s/$Word $Word/\2 \1/"
b a

Note the space between two $Word's.

You are right. Example 5 now works correctly. Thank you!

Daniel B. Martin


All times are GMT -5. The time now is 12:41 AM.