String replace that has spaces

cat rf|nawk '/Use SSL=                0/{n+=1}{if (n==3){sub("Use SSL=                0","Use SSL=                0x1",$0)};print }' > rf2

Fails.

sed 's/Use SSL=              0/Use SSL=              0x1/g' rf > rf2

Fails.

In addition, the goal is to ONLY replace the 2nd occurence of the entire line, here's the line:

Use SSL=             0;          REG_DWORD

Want it changed to:

Use SSL=             0x1;          REG_DWORD

Notice it has all these spaces.

I've tried double, singe quotes, graves, no luck so far.

Any help is greatly appreciated.

Please post sample representative input from "rf" and sample matching output you would expect in "rf2". Please post in code tags so posters can see the space characters.
Though "nawk" says SunOS (or some older unix System V) to me, please post what Operating System and version you have and what Shell you prefer.

Ps "Fails" doesn't mention what actually happened !

The file 'rf' contains many lines of which several are identical, as follows:

Use SSL=                   0;            REG_DWORD

There may be 2-5 identical lines (to make it more complicated, the number of spaces between = and 0 and ; and REG_DWORD could be different on each line or they could be exactly the same.

The server os is solaris 8.

The several attempts made failed to replace the 0; with 0x1 while keeping the format intact;...by fail, nothing was replaced...as if the PATTERN was not recognized.

Thanks for helping.

printf "Use SSL= 0; REG_DWORD\nSomething\nUse SSL= 0; REG_DWORD\nUse SSL= 0; REG_DWORD\n" |
        awk '/Use SSL= *0 *; *REG_DWORD/ && ((++N)==2) { sub(/0/, "0x0"); } 1'

Use SSL= 0; REG_DWORD
Something
Use SSL= 0x0; REG_DWORD
Use SSL= 0; REG_DWORD

$

Thanks.

Can you explain what is happening with your recommendation?

It does not work as typed...what is 'something' supposed to be?

In what way does it 'not work'? What does it do? Show exactly what you did, word for word, letter for letter, keystroke for keystroke.

'something' is a string which is not "Use SSL= 0; REG_DWORD", to demonstrate that it does as you ask, only counting matches of lines like "Use SSL= 0; REG_DWORD". It matches the first one and ignores it, matches the second one and changes it, and does nothing thereafter.

In the "sed" in post #8 there is one too many space both sides of the replace.
If we correct the number of spaces in the "sed" it appears to work.

                        echo "Use SSL=             0;          REG_DWORD" | \
sed 's/Use SSL=             0/Use SSL=             0x1/g' 

./scriptname
Use SSL=             0x1;          REG_DWORD

c/f oribinal line

Use SSL=             0;          REG_DWORD

It will take a "sed" expert to replace the second occurrance (and subsequent?). Not really clear what is required without a better before and after example.

wow...thank you again for your patience and ideas.

while the last idea works from the command line, on my solaris 8 server, changing the /g to /2g, or /g to /2 (since I want the 2nd pattern in the file to be changed) throws no error, and the pattern in the file is not changed.

the errors thrown from the previous idea to this are here, as is the command used:

printf "Use SSL=                0;                      REG_DWORD\nSomething\nUse SSL=                0;                      REG_DWORD\nUse SSL=                0;                      REG_DWORD\n" | awk '/Use SSL= *0 *; *REG_DWORD/ && ((++N==2) { sub(/0/, "0x1"); } 1' rf > rf2

ld.so.1: printf: fatal: libiconv.so.2: open failed: No such file or directory
awk: syntax error near line 1
awk: bailing out near line 1
ksh: 11696 Killed

I think that the awk needs to be nawk on your system.

As for the sed idea we just need an expert to advise how to change only the second occurance of the string.

For my benefit, how big is each file?

Reference post #3. What exactly and precisely defines the second occurance of the string? Is it an exact match for the whole line (including all space characters) or a fuzzy match where the number of space characters varies? We need a better definition of the problem, complete with sample input data and matching expected output data.

This is exactly the contents of the file (the edit post is taking out the extra spaces, in this problem there are 10 spaces between SSL= and 0;, and 15 spaces between 0; and REG_DWORD):

Use SSL=          0;               REG_DWORD
Use SSL=          0;               REG_DWORD

The expected result is as follows:

Use SSL=          0;               REG_DWORD
Use SSL=          0x1;            REG_DWORD

Maintaining the format of each line.

Still not clear to me. Lines with different amount of spaces, but otherwise identical values, are they considered equal?

/usr/xpg4/bin/awk '++A[$1,$2,$3,$4]==2{sub("0;","0x1;")}1' infile

or unequal?

/usr/xpg4/bin/awk '++A[$0]==2{sub("0;","0x1;")}1' infile

Is it for every line (above) or only for lines that start with "Use SSL=" ?

/usr/xpg4/bin/awk '/^Use SSL=/ && ++A[$1,$2,$3,$4]==2{sub("0;","0x1;")}1' infile

and

/usr/xpg4/bin/awk '/^Use SSL=/ && ++A[$0]==2{sub("0;","0x1;")}1' infile

respectively...

And is it only the 2nd occurrence that needs the replacement (like above) and not the 3rd, 4th and 5th, or do they? (in that case then use A[..]++ instead of ++A[..]==2 ). Otherwise please post a larger proper sample of you input file with several lines and the desired output...

There are few words of praise...brilliant...thank you very much.

The goal being to only change the 2nd instance of the pattern (that begins with "Use SSL=" was solved using either of these commands:

/usr/xpg4/bin/awk '/^Use SSL=/&&++A[$1,$2,$3,$4]==2{sub("0;","0x1;")}1' infile

and

/usr/xpg4/bin/awk '/^Use SSL=/&&++A[$0]==2{sub("0;","0x1;")}1' infile

Can you reply with an explanation on what is happening here? Why is /usr/xpg4/bin/awk used? What does the &&++A do? The [$0]? The ==2?, and the 1?

Hi, /usr/xpg4/bin/awk is used because you mentioned you are on Solaris 8 and the standard awk is either broken or ancient, any case it usually not functioning as expected, whereas /usr/xpg4/bin/awk adheres to POSIX specification...

/^Use SSL=/&&++A[$0]==2 means if a line starts with "Use SSL=" and it is the second time that the same line ($0 means the entire line) is encountered, then:
{sub("0;","0x1;")} substitute "0;" by "0x1;" but otherwise leave the line intact.
1 Perform the default action, which is {print $0} , i.e. print the record...

Thanks.

I've never seen &&++A, how is that defined?

How is that different from:

++A[$1,$2,$3,$4]==2

Very interesting actions.

Hi, they are two different thing (I added spaces for clarity in my post above to illustrate). && means AND and ++A[$0] means increase with 1 the value of array element which has the entire line ($0) as an index. If the value equals 2, which is the case the second time the same line is encountered, then perform the (sub) action in curly brackets..

The difference between A[$0] and A[$1,$2,$3,$4] is that in the first case all the spaces and/or tabs are included, so that lines need to be exactly equal for us to conclude that they are the same, if we compare them. In the second case only the fields themselves need to be equal (the spaces between the fields may vary)...

Again thanks.