Why can't OCMod find lines of code? - opencart

I have an issue with OCMod, it randomly seems to not find lines of code, see below:
<file path="catalog/language/english/product/ymmproduct.php">
<operation>
<search trim="true"><![CDATA[
$_['tab_vehicle'] = 'Vehicles';
]]></search>
<add position="replace"><![CDATA[
$_['tab_vehicle'] = 'Bikes';
]]></add>
</operation>
</file>
the file path and ned is correct
i've tried the search with and without trimming [I'm guessing at what 'trim' does because it's not documented]
the line of code I'm searching for is absolutely there - I cut and pasted it from the target file then diff'd the contents.... NO DIFFERENCE.
I've tried it with and without line feeds in the CDATA
Nothing I have tried will find that line of code.
What could the issue be?

OCMod is not robust for a multiline search. If you can figure out how to do a single line search, it will be much more likely to work consistently. Since the file catalog/language/english/product/ymmproduct.php isn't in the default installation, is it yours? Perhaps you can create lines in it that will help guide OCMod so a single line search will work properly.

Related

A Regular Expression that I know is correct, doesn't work with awk. Please advise

Following up on an answer by #dawg to my question how to delete multiple sections in a file based on known patterns, I want to use a regular expression in awk to identify the start of the section(s) I want to delete.
The file I am working with is an xml file. It is in fact the file containing the recently used filenames list (RUFL) in Linux Mint (~/.local/share/recently-used.xbel).
This is how the RUFL is structured:
<?xml version="1.0" encoding="UTF-8"?>
<xbel version="1.0"
xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"
xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"
>
<bookmark href="file:///home/ocor61/Documents/Linux/Linux%20Mint%20Cinnamon%20Keyboard%20Shortcuts.pdf" added="2021-07-18T01:57:02Z" modified="2021-07-18T01:57:02Z" visited="1969-12-31T23:59:59Z">
<info>
<metadata owner="http://freedesktop.org">
<mime:mime-type type="application/pdf"/>
<bookmark:applications>
<bookmark:application name="Document Viewer" exec="&apos;xreader %u&apos;" modified="2021-07-18T01:57:02Z" count="1"/>
</bookmark:applications>
</metadata>
</info>
</bookmark>
<bookmark href="file:///home/ocor61/Documents/Linux/Linux%20Command%20Line%20Cheat%20Sheet.pdf" added="2021-07-18T01:57:09Z" modified="2021-07-18T01:57:09Z" visited="1969-12-31T23:59:59Z">
<info>
<metadata owner="http://freedesktop.org">
<mime:mime-type type="application/pdf"/>
<bookmark:applications>
<bookmark:application name="Document Viewer" exec="&apos;xreader %u&apos;" modified="2021-07-18T01:57:09Z" count="1"/>
</bookmark:applications>
</metadata>
</info>
</bookmark>
<bookmark href="file:///home/ocor61/Documents/work.bfproject" added="2021-07-20T10:52:59Z" modified="2021-07-22T08:41:57Z" visited="1969-12-31T23:59:59Z">
<info>
<metadata owner="http://freedesktop.org">
<mime:mime-type type="application/x-bluefish-project"/>
<bookmark:applications>
<bookmark:application name="bluefish" exec="&apos;bluefish %u&apos;" modified="2021-07-22T08:41:57Z" count="2"/>
</bookmark:applications>
</metadata>
</info>
</bookmark>
</xbel>
I am working on a script to remove filenames from the list. It works fine, but I am also working with an array that contains patterns that should not be used. For example: if the pattern [bookmark] would be used to identify a section that must be removed, the entire file would become unusable. That goes for parts of [bookmark], but also for href, added, info... You get my drift.
So, I want to work with a regexp to counter the problems of entering patterns that cannot be used.
Currently, this is the awk code I am using now (thanks to #dawg):
ENDLINE='</bookmark>'
awk -v f=1 -v st="$1" -v end="$ENDLINE" '
match($0, st) {f=0}
f
match($0, end){f=1}' ~/.local/share/recently-used.xbel
$1 would be the pattern a user enters at the command line, which is part of the file name that must be removed from the RUFL.
The following is the code I would like to use, including the regexp, which doesn't work:
STARTLINE='/(<bookmark href)(.*)($1)(.*)(>)/'
ENDLINE='</bookmark>'
awk -v f=1 -v st="$STARTLINE" -v end="$ENDLINE" '
match($0, st) {f=0}
f
match($0, end){f=1}' ~/.local/share/recently-used.xbel
I have tested the regular expression at https://regexr.com/, so I know it is correct. However, when I use it in my script, this is the error message I am getting:
./ruffle.sh: line 99: syntax error near unexpected token `$0,'
./ruffle.sh: line 99: ` match($0, st) {f=0}'
I have also tried to enter the regexp itself in the awk command line instead of the variable, but that has the same result.
I don't know how to proceed, so any help is appreciated.
The answer to my question lies in how regular expressions can differ when used in different environments. The website I used to check my regexp does so for languages like JS, but not for Bash or likely other shell implementations.
With shellcheck.net as well as by putting the command 'set -vx' in my script right before the awk command, I managed to work things out.
Another mistake I made was to attempt to catch the complete line in the regexp, while I need only the part in that line that can hold the pattern that is entered (which is the part between 'file:' and 'added' in the file ~/.local/share/recently-used.xbel).
The regexp that ultimately works for me now with the variable STARTLINE is:
STARTLINE='file:.*'$1'.*added='
I will have to look into using an xml parser, thanks for the suggestion! For now, however, my script works. Thanks #Sundeep and #EdMorton!

Using sed to replace multiline xml

I'm trying to use sed to edit/change a xml file, but I'm having problems with multilines
The file I want to change has (extract)
<keyStore>
<location>repository/resources/security/apimanager.jks</location>
<password>wso2carbon</password>
</keyStore>
I want to change the password (and only the keyStore password, the file has another password tag)
I'm trying
sed -i 's/\(<keyStore.*>[\s\S]*<password.*>\)[^<>]*\(<\/password.*>\)/\1$WSO2_STORE_PASS\2/g' $WSO2_PATH/$1/repository/conf/broker.xml
but it's not working (change nothing, pattern not found)
If I test the pattern in on-line tester (https://regex101.com/) it seems to work find.
Also, I have tried to replace the [\s\S]* by [^]*, but in this case, sed generate a syntax error.
I'm using Ubuntu 16.04.1.
Any suggestion will be welcome
Parsing XML with regular expressions is always going to be problematic, as XML is not a regular language. Instead, you can use a proper XML parser, for example with XMLStarlet:
xmlstarlet ed --inplace -u "keyStore/password" -v "$WSO2_STORE_PASS" $WSO2_PATH/$1/repository/conf/broker.xml
Sed is not the tool for the job. Use an XML-aware tool, for example xsh:
open { shift } ;
insert text { shift } replace //keyStore/password/text() ;
save :b ;
Run as
xsh script.xsh "$WSO2_PATH/$1/repository/conf/broker.xml" "$WSO2_STORE_PASS"

REGEX Multi-line Search between 2 characters- Powershell

I am unable to apply many of the other powershell regex solutions to help solve my problem. The answer may very well already be on stackoverflow, but my lack of experience with powershell is prohibiting me from deducing how to maniupulate the solutions to my question.
I have a text file containing an XML document tree(I bring in the document tree as one large string into powershell)(edit 1) that includes the HTML tags to establish where certain content is. I need to steal the file name from in between the filename tags. Sometimes both tags and the file name are all on one line, and other times the tags are each on a seperate line as well as the file name. An example of the input data I have is below:
<files>
<file>
<fileName>
ThisTextFileINeedReturned.txt
</fileName>
<lastModifiedTime>1511883780000</lastModifiedTime>
<size>852192</size>
<isDirectory>false</isDirectory>
<isRegularFile>true</isRegularFile>
<isSymbolicLink>false</isSymbolicLink>
<isOther>false</isOther>
<group>group</group>
<transferStatus>Done</transferStatus>
</file>
<file>
<fileName>AnotherTextFileINeedReturned.txt</fileName>
<lastModifiedTime>1511883780000</lastModifiedTime>
<size>852192</size>
<isDirectory>false</isDirectory>
<isRegularFile>true</isRegularFile>
<isSymbolicLink>false</isSymbolicLink>
<isOther>false</isOther>
<group>group</group>
<transferStatus>Done</transferStatus>
</file>
I have created the following code to find the content within the tags thus far. It works if the filename tags and the file name are on the same line. The problem I'm having is in the instance where they are all on seperate lines (the example I provided above). I have already managed to transfer the large string above into $xmldata.
$xmldata -match '<fileName>(.*?)(</fileName>)'
$matches
Using the example text I displayed above, the output I receive is as follows:
<fileName>AnotherTextFileINeedReturned.txt</fileName>
I'm ok with receiving the tags, but I also need the name of the file that is on multiple lines. Like this...
<fileName>
ThisTextFileINeedReturned.txt
</fileName>
<fileName>AnotherTextFileINeedReturned.txt</fileName>
Or any variation that would give me both of the names of the text files. I have seen the (?m) part used before, but I haven't been able to successfully implement it. Thanks in advance for the help!! Let me know if you need any other information!
You should be able to get around that without using any regex. Powershell supports XML pretty well. Extracting the filename would be as easy as:
$Xml = #"
<files>
<file>
<fileName>
ThisTextFileINeedReturned.txt
</fileName>
<lastModifiedTime>1511883780000</lastModifiedTime>
<size>852192</size>
<isDirectory>false</isDirectory>
<isRegularFile>true</isRegularFile>
<isSymbolicLink>false</isSymbolicLink>
<isOther>false</isOther>
<group>group</group>
<transferStatus>Done</transferStatus>
</file>
<file>
<fileName>AnotherTextFileINeedReturned.txt</fileName>
<lastModifiedTime>1511883780000</lastModifiedTime>
<size>852192</size>
<isDirectory>false</isDirectory>
<isRegularFile>true</isRegularFile>
<isSymbolicLink>false</isSymbolicLink>
<isOther>false</isOther>
<group>group</group>
<transferStatus>Done</transferStatus>
</file>
</files>
"#
Select-Xml -Content $Xml -XPath "//files/file/fileName" | foreach {$_.node.InnerXML.Trim()}
You not explainen how you get your data but I guess you are using Get-Content to retrieve your source file. Get-Content reads the content one line at a time and returns a collection of objects, each of which represents a line of content. In other words, you're probably doing a Match on each separate line and therefor do no find the matches that are spread over multiple lines.
If this is indeed the case, the solution would be to simply join the lines first:
($xmldata -Join "") -match '<fileName>(.*?)(</fileName>)'
And check your matches, e.g.:
$Matches[0]

VQMod offset issue in OpenCart

I`m trying to replace a chunk of code on the model with custom code, that I wrote.
Here is the code. I works, but it leaves a lot of offset.
Maybe there is a better way to do this
<operation info="Example of the vQmod">
<search position="replace" offset="3"><![CDATA[
Some code I want to Replace
Some code I want to Replace
Some code I want to Replace
]]></search>
<add><![CDATA[
Replaced Code
Replaced Code
Replaced Code
]]></add>
</operation>
Vqmods offset value is for replacing a line and the following x lines, however the search is for one line only. Vqmod doesn't match multiple lines in search.
Example :
Input
public function index() {
$a = rand();
$b = rand();
if ($a == $b) {
echo 'oh noes';
return false;
}
}
Script
<?xml version="1.0" encoding="UTF-8"?>
<modification>
<id>Replace many lines with one</id>
<version>1.0</version>
<vqmver>2.X</vqmver>
<author>xxx</author>
<file name="path/to/testfile.php">
<operation info="Replace index function">
<search position="replace" offset="7"><![CDATA[
public function index() {
]]></search>
<add><![CDATA[
public function index($arr = array()) {
foreach ($arr as $a) {
echo $a;
}
}
]]></add>
</operation>
</file>
</modification>
Output
public function index($arr = array()) {
foreach ($arr as $a) {
echo $a;
}
}
Note : There are still 7 blank lines. The offset clears the extra 7 lines of code from the input, but the replaced code is added in place of the initial line. So there will be 7 extra spaces after the new code, but it will not affect the code functionality, only the look of the vqcache file which is of no importance.
In Opencart, you cannot search for multiple lines of code and replace it with new multiple lines of codes. It can only search a single line and then replace or add with single line or multiple lines of code.
Offset is to search a single line of code and then offset the number of lines below and then replace or add new coding. Something like this:
<operation info="Example of the vQmod">
<search position="replace" offset="3"><![CDATA[
code I want to Replace at offset line 3
]]></search>
<add><![CDATA[
Replaced Code
add code
add code
]]></add>
</operation>

How can I remove everything after a word on every line of a text file?

I have a text file that looks a bit like this
356, http://linkgoeshere.com/4445555 title="The Chariot"> <br />
356, http://linkgoeshere.com/4445555 title="fddsfssfd"> <br />
356, http://linkgoeshere.com/4445555 title="T3434534535"> <br />
I want to just leave everything up to the link and remove everything after but each part after is unique apart from the title= so I can't do find and replace.
(About 800 lines of this btw)
Is there any way I can do this using programming?
Thanks.
In Notepad++ you can do this with find and replace using Regular expression
Click menu Search --> Replace...
In Search Mode select Regular expression
Enter the regular expression \stitle=".*$ in Find what
Make Replace with box empty
Click Replace all
Tested in version 6.2.2
This should also work in other editors supporting find and replace using Regular expressions.
Editor way (vim):
open your file with vim, type :%s/ title=.$//g you would have seen the result.
in fact any Editor supports regex replace would work.
script programming:
sed
(note:the command below will make the change in place.)
sed -i 's/ title=.$//' file
awk:
tricky way, without regex:
awk '{print $1,$2}' file
you see the output on stdout. you could redirect it to a file by awk... >newFile
Excel
If your editor doesn't support regular expressions, use Excel to import the file as a csv file (Data -> From Text) and tell excel to use the space as field delimiter. Then export the first two columns as a new csv file.