LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   yet another SED question from a newbie (lengthy one) (http://www.linuxquestions.org/questions/programming-9/yet-another-sed-question-from-a-newbie-lengthy-one-698115/)

dhomes 01-18-2009 08:55 AM

yet another SED question from a newbie (lengthy one)
 
Hi all, I've been looking at the forums for a proper solution to my problem but can't seem to find it.

Question is, I have a file XXX (it's an WordML file, where I extracted the XML document.xml) where I have placed a Val1, to be replaced by the contents of the /etc/inedt.conf file (right now I'm using the whole file, when it works I'll filter out the commented # lines)

Just looking at the top 10 lines (for good measure), I have:


# See "man 8 inetd" for more information.
#
# If you make changes to this file, either reboot your machine or restart
# inetd, so that it will re-read this file.
# "net stop inetd" / "cygrunsrv -E inetd" / "telinit 1"
# "net start inetd" / "cygrunsrv -S inetd" / "telinit 3"
# (depending on how the inetd service is installed on your machine. See
# /usr/share/doc/Cygwin/inetutils-x.y.z.README for more information)
#
# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args>

so you can see it has all these nice characters " / ( ) < > and also \ later down the file

Trying about everything a newbie could, I trying putting this code (i know i could use -e to keep it in one line, but just to comment and uncomment stuff in my trying)

cat /etc/inetd.conf > _t1
cat _t1 | sed s/^#/\\\\#/g > _t2
cat _t2 | sed s/"<"/\\"\<"/g > _t3
cat _t3 | sed s/">"/\\"\>"/g > _t4
cat _t4 | sed s/"("/\\"(>"/g > _t5
cat _t5 | sed s/")"/\\")>"/g > _t6
str=`cat _t6`

after which i end up with (top ten lines of _t6):

\\# See "man 8 inetd" for more information.
\\#
\\# If you make changes to this file, either reboot your machine or restart
\\# inetd, so that it will re-read this file.
\\# "net stop inetd" / "cygrunsrv -E inetd" / "telinit 1"
\\# "net start inetd" / "cygrunsrv -S inetd" / "telinit 3"
\\# (>depending on how the inetd service is installed on your machine. See
\\# /usr/share/doc/Cygwin/inetutils-x.y.z.README for more information)>
\\#
\\# \<service_name\> \<sock_type\> \<proto\> \<flags\> \<user\> \<server_path\> \<args\>

when i finally try sed to replace Val1 by $str:
cat document.xml | sed "s_Val1_$str_" > _tmp

I end up getting:
>>>> sed: -e expression #1, char 218: unterminated `s` command

What I'm doing wrong? carriage returns? need to add \ before / ???

all help s appreciated, i know this is one lengthy question but wanted to illustrate the problem as much as i could

thanks in advance.

pixellany 01-18-2009 09:32 AM

Quote:

when i finally try sed to replace Val1 by $str:
cat document.xml | sed "s_Val1_$str_" > _tmp

I end up getting:
>>>> sed: -e expression #1, char 218: unterminated `s` command
I suspect that the key is in the contents of $str. Note that it is complaining about character #218, which can only be part of the contents of $str.

If--eg--$str contains "_" then that would be an issue. (Simply use a different delimiter for the "s" command.

dhomes 01-18-2009 10:44 AM

no man, just changed several characters for sed that do not show up when using grep on the _t6, like '=' '?' "~" "!"

and get the same problem (some are at a different character other than #218) but still won't work

still looking for a solution :(

pixellany 01-18-2009 10:52 AM

Hmmm.....

Show us the contents of $str. There is obviously **something** in there that SED does not like.

ta0kira 01-18-2009 12:13 PM

You need to use the r command in some manner. For example, find the string and (print everything that isn't the string) then insert the file with r instead of printing the string. I don't have time at the moment to try to write it out, but this should be a lot easier if you make a short program of it.
http://www.grymoire.com/Unix/Sed.html#uh-37

ta0kira

PTrenholme 01-18-2009 12:14 PM

Try this, where the program is the last line:
Code:

#!/bin/bash
cat <<EOF >/tmp/dhomes
# See "man 8 inetd" for more information.
#
# If you make changes to this file, either reboot your machine or restart
# inetd, so that it will re-read this file.
# "net stop inetd" / "cygrunsrv -E inetd" / "telinit 1"
# "net start inetd" / "cygrunsrv -S inetd" / "telinit 3"
# (depending on how the inetd service is installed on your machine. See
# /usr/share/doc/Cygwin/inetutils-x.y.z.README for more information)
#
# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args>
EOF
gawk '{ print gensub(/([\\\/<>()#\"])/,"\\\\\\1","G");}' /tmp/dhomes

which produces:
Code:

$ ./dhomes
\# See \"man 8 inetd\" for more information.
\#
\# If you make changes to this file, either reboot your machine or restart
\# inetd, so that it will re-read this file.
\# \"net stop inetd\" \/ \"cygrunsrv -E inetd\" \/ \"telinit 1\"
\# \"net start inetd\" \/ \"cygrunsrv -S inetd\" \/ \"telinit 3\"
\# \(depending on how the inetd service is installed on your machine. See
\# \/usr\/share\/doc\/Cygwin\/inetutils-x.y.z.README for more information\)
\#
\# \<service_name\> \<sock_type\> \<proto\> \<flags\> \<user\> \<server_path\> \<args\>


PTrenholme 01-18-2009 12:16 PM

Since you asked about sed:
Code:

$ sed 's/\([\\\/<>()#\"]\)/\\\1/g' /tmp/dhomes
\# See \"man 8 inetd\" for more information.
\#
\# If you make changes to this file, either reboot your machine or restart
\# inetd, so that it will re-read this file.
\# \"net stop inetd\" \/ \"cygrunsrv -E inetd\" \/ \"telinit 1\"
\# \"net start inetd\" \/ \"cygrunsrv -S inetd\" \/ \"telinit 3\"
\# \(depending on how the inetd service is installed on your machine. See
\# \/usr\/share\/doc\/Cygwin\/inetutils-x.y.z.README for more information\)
\#
\# \<service_name\> \<sock_type\> \<proto\> \<flags\> \<user\> \<server_path\> \<args\>


ta0kira 01-18-2009 12:33 PM

Quote:

Originally Posted by PTrenholme (Post 3412941)
Since you asked about sed:

There really isn't a point to adding all of those ridiculous escapes since sed allows the direct insertion of a file, anyway.
ta0kira

PS # doesn't count when it's within "", e.g. echo " #hello" | sed 's/ #hell/something/'.

colucix 01-18-2009 12:46 PM

I'd stick with the suggestion by ta0kira. The str variable has the content of a whole file. This arises the problem of multi-lines patterns, not to mention the plenty of special characters, escapes and hashes. If you really want to put the content of the file in place of the Val1 string, do something like:
Code:

sed '/Val1/ {
    r _t6
    d }' document.xml

This will replace the line containing Val1 with the content of the file _t6. Be sure Val1 is alone in a line, otherwise you will lose some other relevant content of the original file.

dhomes 01-18-2009 01:54 PM

@colucix, i tried your suggestion and i no longer have an error, but alas, Val2 is not replaced, just stays there:

1: cat < /etc/inetd.conf > _tmp

2: cat row.txt | sed "s_Val1_1111_" > t.tmp

3: sed '/Val2/ {
r _tmp
d }' t.tmp

4: cat t.tmp | sed "s_Val3_3333_" >> nr.txt

row.txt is a file with 3 values to be replaced (they are not giving any trouble when i actually use variables $str1 y $str3

i made sure Val2 was on its own line in row.txt:

.... w:val="24"/></w:rPr><w:t>

Val2

</w:t></w:r></w:p><w:p> .....

and i end up with exactly the same in nr.txt (except Val1 and Val3 replaced by 1111 3333)

still, i do appreciate the ideas and suggestions given so far, i think i'm close to fix this with a little more help

colucix 01-18-2009 02:06 PM

Quote:

Originally Posted by dhomes (Post 3413017)
i no longer have an error, but alas, Val2 is not replaced, just stays there:

3: sed '/Val2/ {
r _tmp
d }' t.tmp

In the commands you've shown, this is the only one for which you've not redirected the output to a file. Take in mind that sed does not edit the original file, unless you use the -i option. Try again, redirecting the output to another temporary file.

You can also try the option -i, but beware it is dangerous for testing purposes: if something goes wrong and the result is not the expected one, the original file is lost. A good practice is to preserve a backup copy of the original file before editing it with sed.

dhomes 01-18-2009 02:49 PM

I'm surely am missing something.

1: cat < /etc/inetd.conf > _tmp
2: cat row.txt | sed "s_Val1_1111_" > t.tmp
3: sed '/Val2/ {
r _tmp
d }' t.tmp > t2.tmp

4: cat t2.tmp | sed "s_Val3_3333_" >> nr.txt

- t.tmp gets it's Val1 replaced by 1111

- t2.tmp has all the info of t.tmp EXCEPT Val2 is just now a just a blank line, in the previous code it had Val2 left in place

- 4: cat t2.tmp | sed "s_Val3_3333_" >> nr.txt gets me Val3 also replaced

thanks for the help so far colucix

colucix 01-18-2009 03:50 PM

I cannot be of much help so far, since I cannot see the actual content of your temporary files in the process. I can only demonstrate the way it works doing a test:
Code:

$ cat t.tmp
Hello World!
Val2
Hello dhomes!
$ cat _tmp
This is the text I want to put in
place of Val2 in file t.tmp using
sed. It consists of three lines.
$ sed '/Val2/ {
> r _tmp
> d }' t.tmp > t2.tmp

$ cat t2.tmp
Hello World!
This is the text I want to put in
place of Val2 in file t.tmp using
sed. It consists of three lines.
Hello dhomes!
$



All times are GMT -5. The time now is 04:20 AM.