[Solved] Replace the second pattern alone in VI.

I have lines like:

table10 table_name_10 table10 table_name_10
table20 table_name_20 table20 table_name_20
table30 table_name_30 table30 table_name_30

I want to change the second "table_names" in all lines to test_table_name. Required output would be:

table10 table_name_10 table10 test_table_name_10
table20 table_name_20 table20 test_table_name_20
table30 table_name_30 table30 test_table_name_30

How do I do that in VI editor?

This might not be pretty, but you could do it in three steps:

:%s/table_name_/SOMETHING_UNIQUE/
:%s/table_name_/test_table_name_/
:%s/SOMETHING_UNIQUE/table_name_/

something to start with:

sed 's/\(.*[ ]\)\(.*\)/\1test_\2/' myFile

That will replace first occurrences of "table_name". I don't want to touch the second column (first occurrence). Only change the values in the last column (second occurrence).

---------- Post updated at 01:59 PM ---------- Previous update was at 01:57 PM ----------

I am looking for steps in VI editor not sed command.

You can surely adopt what's been given in sed - try it.

I tried something like '%s/\(.*[ ]\)\(.*\)/\1test_\2/'

It doesn't work.

works fine in my case:

%s/\(.*[ ]\)\(.*\)/\1test_\2/

It replaces all words in the last columns of all lines when there is no word "table_name" in those lines.

How about this... :%s/^.* /&test_/g

misread the requirement - your sample data could have been a bit more representative/variable to illustrate the requirement. Try this:

%s/table_name/test_table_name/2

Thanks, same issue. It replaces all words in the last columns on all lines (irrespective of whether there is the word "table_name" in those lines).

---------- Post updated at 02:28 PM ---------- Previous update was at 02:24 PM ----------

Yeah, that's what all links on google say should work, but it just doesn't work for me. Maybe it is my VI editor issue. :confused:

this will attach 'test_' to the LAST column regardless of its value.
The OP want to prefix 'test_' to second occurrence of 'table_name' ONLY to its SECOND occurrence - it can be a 3 column or the LAST column...
The sample file was not really representative of the requirement.

do cat -vet myFile and post it here within code tags.

In your sample you show that every line contains exactly two occurrences of table_name in each line in your file. Is that true in the file you're editing?

Could some lines have zero or only one occurrence of table_name ?

Could any lines have three or more occurrences of table_name ?

Here are the contents of my file:

cat -vet temp.lst

-- Configure test table connections ---$
$
table10 table_name_10 table10 table_name_10$
table20 table_name_20 table20 table_name_20$
table30 table_name_30 table30 table_name_30$
$
-- Configure view connections ---$
$
view10 view_name_10 view10 view_name_10$
view20 view_name_20 view20 view_name_20$
view30 view_name_30 view30 view_name_30$
$

---------- Post updated at 02:43 PM ---------- Previous update was at 02:40 PM ----------

Thanks, I've posted the contents of my file above. There are just 3 lines with the words "table_name", in 2 columns. I need to replace those ones in the last column (second occurrence).

For the given data the following is an easy way to do it:

:g/\(.* \)\(table_name\)/s//\1test_\2/

This will prepend "test_" to the last string containing "<space>table_name" on any line that contains one or more occurrences of that string.

PS. In vi (and ed, and ex) replacing the 1st or last occurrence of something on a line is easy. Replacing the 2nd occurrence of something that may appear 2 or more times takes multiple steps.

Yeah, it works, thanks! :b:

I noticed that some of my files have owner prefix for tables like this:

-- Configure test table connections ---
table10 owner.table_name_10 table10 owner.table_name_10
table20 owner.table_name_20 table20 owner.table_name_20
table30 owner.table_name_30 table30 owner.table_name_30
-- Configure view connections ---
view10 owner.view_name_10 view10 owner.view_name_10
view20 owner.view_name_20 view20 owner.view_name_20
view30 owner.view_name_30 view30 owner.view_name_30

I tried the below options, it didn't do anything:

:g/\(.* \)\(table_name\)/s//\1test_\2/

or

:g/\(.* \)\(owner.table_name\)/s//\1test_\2/

Now the below command looks like it prefixes the last column instead of prefixing the exact pattern:

:g/\(.* \)\(owner\.table_name\)/s//\1test_\2/

Output:

-- Configure test table connections ---
table10 owner.table_name_10 table10 test_owner.table_name_10
table20 owner.table_name_20 table20 test_owner.table_name_20
table30 owner.table_name_30 table30 test_owner.table_name_30

Required output is:

-- Configure test table connections ---
table10 owner.table_name_10 table10 owner.test_table_name_10
table20 owner.table_name_20 table20 owner.test_table_name_20
table30 owner.table_name_30 table30 owner.test_table_name_30

A variation of Don's theme - to handle both cases:

:g/\(.* \)\([^.]*[.]*\)\(table_name\)/s//\1\2test_\3/

Try:

:g/\(.*[ .]\)\(table_name\)/s//\1test_\2/

which will look for a space or a period before "table_name" instead of:

:g/\(.* \)\(table_name\)/s//\1test_\2/

Which only accepts a space before "table_name".

That worked just fine!

Thanks :b:

---------- Post updated at 04:11 PM ---------- Previous update was at 04:10 PM ----------

That also worked just fine!

Thanks :b: