I have a tricky problem. I need to make a minor change to a large number of xml files (500+). The change involves switching a value from 'false' to 'true.' The line that needs to change looks like this:
<VoltageIsMeasuredLineLine>false</VoltageIsMeasuredLineLine>
And it needs to become:
<VoltageIsMeasuredLineLine>true</VoltageIsMeasuredLineLine>
Unfortunately there are numerous instances of this set of tags in each file, so we can't do a simple find and replace. The thing that makes this set of tags unique is that they come some lines after:
<CID>STATIONNAME.BUS.STATIONNAME.DKV</CID>
However, each file has a different station name, so I had used wildcards to filter them out.
<CID>.*.BUS.*.DKV</CID>
So the code looks like this:
<CID>STATIONNAME.BUS.STATIONNAME.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<VoltageIsMeasuredLineLine>false</VoltageIsMeasuredLineLine>
And other sections in the code look like:
<CID>STATIONNAME.COLR.STATIONNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<VoltageIsMeasuredLineLine>false</VoltageIsMeasuredLineLine>
So I'm using the CID .BUS .DKV line as a starting point. Basically I need to change the first occurance of the VoltageisMeasured line that comes directly AFTER the CID .BUS .DKV line. But there's a lot of other lines in between (none of which are consistent from file to file) that I don't care about and are messing up my search.
I was suggested to try a Lookahead, but it did not work. This it the code I was told to try:
(?!<CID>.*.BUS.*.DKV</CID>(.*?)<VoltageIsMeasuredLineLine>false</VoltageIsMeasuredLineLine>
Hower, that line is also returning the lines without .BUS and .DKV, which are the really important factors in determining this section's uniqueness. How can I modify this Lookahead so that it only returns sections that had the .BUS and .DKV in the CID part?
Another idea I had was to select everything in between the CID and Voltage parts, keep the selections in groups, and then print the first two groups as-is, and replace the third. Like this:
(<CID>.*.BUS.*.DKV</CID>)(.*)(<VoltageIsMeasuredLineLine>false</VoltageIsMeasuredLineLine>)
And replace with
\1\2<VoltageIsMeasuredLineLine>true</VoltageIsMeasuredLineLine>
But something is still wrong with the CID part. I'm sure these wildcards are part of the problem but I've hit a wall. Any help appreciated!
Try the following in Notepad++ (Version >= 6.0) with replace
Activate Option matches newline and
set in Find what:
(<CID>[A-Za-z\.]*BUS[A-Za-z\.]*</CID>.*?<VoltageIsMeasuredLineLine>)false
and in Replace with:
\1true
The assumption is that every STATIONNAME.BUS.STATIONNAME.DKV has one corresponding VoltageIsMeasuredLineLine (as I read from your question)
The trick is, to use greedy search. I look for the first VoltageIsMeasuredLineLine after VoltageIsMeasuredLineLine
Related
In a data file I need to find all lines that contain less than 10 times the pattern |^|
I need them in two ways:
a search, so I can go through the file and examine the data
as a list to be copied, including the next line
I use Gvim in Windows.
So far I've tried along the lines of:
/[|^|]{,9}
/[|^|]*{,9}
:g/\v(\|[^|^|]*){,9}/p
Is anyone able to help me?
Edit: an example (as real data is not allowed to be used)
abc|^|def|^|ghi|^|jkl|^|mno|^|pqr|^|stu|^|vwx|^|yza|^|bcd|^|efg
abc|^|def|^|ghi|^|jkl|^|mno|^|pqr|^|stu|^|vwx|^|yza|^|
bcd|^|efg
abc|^|def|^|ghi|^|jkl|^|mno|^|pqr|^|stu|^|vwx|^|yza|^|bcd|^|efg
Final solution:
:v/\v(\|\^\|.*){10}
I tried this one. I think it will help.
/\(|^|.*\)\{10}
or with \v
/\v(\|\^\|.*){10}
The list name is disk and its below:
disks
['5000cca025884d5\n', '5000cca025a1ee6\n']
The file name is p and its below:
c0t5000CCA025884D5Cd0 solaris
/scsi_vhci/disk#g5000cca025884d5c
c0t5000CCA025A1EE6Cd0
/scsi_vhci/disk#g5000cca025a1ee6c
c3t50060E8007DB981Ad1
/pci#400/pci#1/pci#0/pci#8/SUNW,emlxs#0/fp#0,0/ssd#w50060e8007db981a,1
c3t50060E8007DB981Ad2
/pci#400/pci#1/pci#0/pci#8/SUNW,emlxs#0/fp#0,0/ssd#w50060e8007db981a,2
c3t50060E8007DB981Ad3
/pci#400/pci#1/pci#0/pci#8/SUNW,emlxs#0/fp#0,0/ssd#w50060e8007db981a,3
c3t50060E8007DB981Ad4
i want to search elements of a list in file
There are a couple of things to look at here:
I haven't actually used re.match() before, but I can see the first issue: Your list of disks has a newline character after every entry, so that will mess up matches. Also, re.match() only matches from the start of the line. Your lines start with numbers, so you need to search during the line, using re.search(). Finally, you should make it case insensitive; one option to d this is to make everything lowercase just as your disks list is.
try adapting your loop as so:
#.strip() will get rid of new lines and .lower() will make the string lowercase
for line in q:
if re.search(disks[0].strip(),line.lower()):
print line
If that doesn't fix it, I would try making it print out disks[0].strip() and line for every iteration of the loop (not just when it matches the if clause) to make sure it's reading in what you think it is.
I'm having a bit of trouble using parenthesis in a vim string. I just need to add a set of parenthesis around 3 digits, but I can't seem to find where I'm suppose to correctly place them. So for example; I would have to place them around a phone number such as: 2015551212.
Right now I have a strings that separates the numbers and puts a hyphen between them. For example; 201 555-1212. So I just need the parenthesis. The final result should look like: (201) 555-1212
The string I have so far is this: s/\(\d\{3}\)\(\d\{3}\)/\1 \2-/g
How might I go about doing this?
Thanks
Just add the parens around the \1 in your replacement.
s/\(\d\{3\}\)\(\d\{3\}\)/(\1) \2-/g
If you want to go in reverse, and change "(800) 555-1212" to "8005551212", you can use something like this:
s/(\(\d\d\d\))\ \(\d\d\d\)-\(\d\d\d\d\)/\1\2\3/g
Instead of the \d\d\d, you could use \d\{3\}, but that is more trouble to type.
I have been a terrible person as of late when it comes to Minecraft. I have over-modded it to the point that I need to completely re-write the IDs of them all.
The only problem is that... It'll take about a couple of hours jut to re-write them ONCE, not to mention if any of them collide with the original game. So, in order to save time, I figured I'd use Vim, but after reading through several of the helpful posts on here, I still only know a minimal amount about the replacement feature/command. Here's what I'm trying to do:
Replace this
I:exampleModnamePath.id=16389
I:exampleModnamePat2.id=19657
Etc.
With this
I:exampleModnamePath.id=20000
I:exampleModnamePath.id=20001
Etc.
This continues for a while, and to those who answer, could you please inform me of how it works, so I don't have to ask these questions all the time?
For your perusal:
:let g:num = 1
:g/\.id=\d\+$/exec 's!\.id=\d\+$!.id='.g:num.'! | let g:num=g:num+1'
This is slightly simplified version of my code for (re)numbering chapters in the ebooks.
Idea in a nutshell: use :g to run something over affected lines; use :exec to generate/run new substitution command AND increment the counter. Tried it once and was surprised to find that the trick worked. Was inspired by my previous toying with :g//s/// combo.
I'm not sure what is the rule you are using to choose which number to use for replacement but if all you need
is just a new number that doesn't collide with previous ones you could try just replacing the first digit
with something in a range not used. Something like replacing 16389 with 76389
To do that you could use this :s/Path.id=.\(.*\)/Path.id=7\1
That would search for the string Path.id= followed by a single character and then a group of more characters.
I will replace it with the string Path.id=7 and the group previously selected.
You could make it more selectiv adding letters before Path.id to match only certain types of paths.
I have an XML file where I only care about the size attribute of a certain element.
First I used
global!/<proto name="geninfo"/d
to delete all lines that I don't care about. That leaves me a whole bunch of lines that look like this:
<proto name="geninfo" pos="0" showname="General information" size="174">
I want to delete everything but the value for "size."
My plan was to use substitute to get rid of everything not matching 'size="[digit]"', the remove the string 'size' and the quotes but I can't figure out how to substitute the negation of a string.
Any idea how to do it, or ideas on a better way to achieve this? Basically I want to end up with a file with one number (the size) per line.
You can use matching groups:
:%s/^.*size="\([0-9]*\)".*$/\1/
This will replace lines that contain size="N" by just N and not touch other lines.
Explanation: this will look for a line that contains some random characters, then somewhere the chain size=", then digits, then ", then some more random characters, then the end of the line. Now what I did is that I wrapped the digits in (escaped) parenthesis. That creates a group. In the second part of the search-and-replace command, I essentially say "I want to replace the whole line with just the contents of that first group" (referred to as \1).
:v:size="\d\+":d|%s:.*size="\([^"]\+\)".*:\1:
The first command (until the | deletes every line which does not match the size="<SOMEDIGIT(S)>" pattern, the second (%s... removes everything before and after size attr's " (and " will also be removed).
HTH