Find string and replace another line in linux [closed] - linux

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have an xml file which looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Station name="XxXx" >
<Inverter name="0701">
<String name="07.01.01-1">
<Converter sku="31570014-0900 A" sn="2116K000551" mac="548280000227" ts="01"/>
</String>
<String name="07.01.01-2">
<Converter sku="31570014-0900 A" sn="1716K000232" mac="4482800000E8" ts="02"/>
</String>
I need a script (or better one linux command) that can find in this file a String with name="07.01.01-1" for example, and change in the next line sn="2116K000551" to sn="11111111", and delete everything till the end of the line (means mac="xxx" ts="xx"), except closing tag "/>", and save this file. I'm trying to do it with sed, but not successfully for now. Is there a one linux command that can do it? I would very much appreciate any suggestions.

The right way with xmlstarlet tool:
xmlstarlet ed -u '//String[contains(#name, "07.01.01-1") and ./Converter/#sn = "2116K000551"]
/Converter/#sn' -v 11111111 \
-d '//String[contains(#name,"07.01.01-1")]
/Converter/#*[name()="mac" or name()="ts"]' file.xml
The output:
<?xml version="1.0" encoding="utf-8"?>
<Station name="XxXx">
<Inverter name="0701">
<String name="07.01.01-1">
<Converter sku="31570014-0900 A" sn="11111111"/>
</String>
<String name="07.01.01-2">
<Converter sku="31570014-0900 A" sn="1716K000232" mac="4482800000E8" ts="02"/>
</String>
</Inverter>
</Station>
To modify the file in-place - add -L option: xmlstarlet ed -L -u ....

Related

Reading source files in MSVS project using xmlstarlet

I am trying to get the source files and include directories from a vcxproj file. Eg of vcsproj:
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
....
<ItemGroup>
<ClCompile Include="$(SrcDir)d1\f1cpp" />
<ClCompile Include="$(SrcDir)d2\f2.cpp" />
</ItemGroup>
...
</Project>
I tried this:
xmlstarlet sel -t -v "//_:ItemGroup/ClCompile/#Include" myProj.vcxproj but didn't work.
However, when I tried this (copying the code from some page that I came across), it works:
echo '<?xml version="1.0" encoding="utf-8"?> <ELEMENT xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<SUB_ELEMENT attribute="attr_value"/>
</ELEMENT>' | xmlstarlet sel -t -v '//_:SUB_ELEMENT/#attribute' --nl
o/p: attr_value
I don't see how the two are different with respect to reading an attribute value from an xml with a namespace. I further tried a stripped down version of the vcxproj file:
echo '<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SrcDir)d1\f1cpp" /> </ItemGroup> </Project>' | xmlstarlet sel -t -v '//_:ItemGroup/#Include' --nl
o/p: <no o/p>
Any indication on why it is not working or how to get this to work would be very helpful.
Edit: Expected output from the vcxproj would be a list of filenames. For the above command it would be $(SrcDir)d1\f1cpp
Any indication on why it is not working or how to get this to work would be very helpful
Since you're using the default namespace add the _:
shortcut on the node test in each
location step,
and the -T (--text)
option to make text mode output:
xmlstarlet select -T -t -v "//_:ItemGroup/_:ClCompile/#Include" -n file.xml

Bash string operation [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am trying to translate markdown file into confluence markup as a complete beginner.
I need to make [Title](https:// site.com) into [Title|https:// site.com]. If it was just one link, i could add it to a var and printf it, but I am having trouble figuring out how to do it if I have 10 links for example.
Previously I used CONTENT=$(echo "${CONTENT//# /h1. }") to replace strings but since now every string is different, I am stuck at how to solve this. I found the solution written in javascript: http://chunpu.github.io/markdown2confluence/browser but fail to understand how to do it in bash.
For this test file
$ cat file
[Title](https://site1.com)
[Title](https://site2.com)
[Title](https://site3.com)
[Title](https://site4.com)
[Title](https://site5.com)
[Title](https://site6.com)
[Title](https://site7.com)
[Title](https://site8.com)
[Title](https://site9.com)
[Title](https://site10.com)
Sed variant:
$ sed 's/\](/|/;s/)/\]/' file
[Title|https://site1.com]
[Title|https://site2.com]
[Title|https://site3.com]
[Title|https://site4.com]
[Title|https://site5.com]
[Title|https://site6.com]
[Title|https://site7.com]
[Title|https://site8.com]
[Title|https://site9.com]
[Title|https://site10.com]
Bash variant:
while read -r line; do
line=${line//](/|}
line=${line//)/]}
echo $line
done < file
[Title|https://site1.com]
[Title|https://site2.com]
[Title|https://site3.com]
[Title|https://site4.com]
[Title|https://site5.com]
[Title|https://site6.com]
[Title|https://site7.com]
[Title|https://site8.com]
[Title|https://site9.com]
[Title|https://site10.com]
Awk variant:
$ awk '{ sub(/\]\(/, "|"); sub(/\)/, "]"); print }' file
[Title|https://site1.com]
[Title|https://site2.com]
[Title|https://site3.com]
[Title|https://site4.com]
[Title|https://site5.com]
[Title|https://site6.com]
[Title|https://site7.com]
[Title|https://site8.com]
[Title|https://site9.com]
[Title|https://site10.com]

AsciiDoctor: How can I add custom xmlns'

How can I add a custom xmlns in the output when I convert an asciidoc file with AsciiDoctor?
I'd like to add xmlns:xi="http://www.w3.org/2001/XInclude" in the top book tag.
The current implementation seems to generate:
<?xml version="1.0" encoding="UTF-8"?>
<?asciidoc-toc?>
<?asciidoc-numbered?>
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info>
<title>title</title>
</info>
</book>
from this:
= title
:lang: en
When I run:
$ asciidoctor -b docbook5 -d book -o out.xml source.txt
There is a built-in attribute xmlns, but it seems to be for docbook 4.5.
The reason I want to use XInclude is to include some xml files from Docinfo files and Passthrough Blocks
With a bit of research inside the asciidoctor code it quickly became clear that the part you'd like to modify is fairly static.
See asciidoctor/converter/docbook5.rb Line 44 for more info.
The best approach is to create a postprocessor extension which modifies the output. The example below is just to show a possible implementation.
Create a file with the following content and call it docbook_postprocessor.rb.
class Docbook5XiPostprocessor < Asciidoctor::Extensions::Postprocessor
def process document, output
if document.basebackend? 'docbook'
input_regex = %r{^(<.*xmlns:xl="http://www.w3.org/1999/xlink") (version="5.0".*>)}
replacement = %(\\1 xmlns:xi="http://www.w3.org/2001/XInclude" \\2)
output = output.sub(input_regex, replacement)
end
output
end
end
Asciidoctor::Extensions.register do
postprocessor Docbook5XiPostprocessor
end
Note: The above extension is for the sake of brevity placed in the same directory as the asciidoctor source file called source.adoc.
The run the asciidoctor command with the -r ./docbook_postprocessor.rb parameters.
$ asciidoctor -r ./docbook_postprocessor.rb -b docbook5 -d book -o - source.adoc
<?xml version="1.0" encoding="UTF-8"?>
<?asciidoc-toc?>
<?asciidoc-numbered?>
<book
xmlns="http://docbook.org/ns/docbook"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:lang="en">
<info>
<title>test</title>
<date>2020-12-19</date>
</info>
</book>
* Above output has been slightly reformatted to eliminate the scrollbar
Creating ruby gem with the above code for easier distribution is a task left to the reader.

How to sort strings.xml alphabetically in Android Studio

Hello is there a way to sort the string names alphabetically in strings.xml ?
It should sort it like this
Before
<string name="ccc">CText</string>
<string name="aaa">AText</string>
<string name="bbb">BText</string>
After
<string name="aaa">AText</string>
<string name="bbb">BText</string>
<string name="ccc">CText</string>
I am using Android Studio 1.5.1
I used AndroidXmlSorter plugin and it works perfectly for me.
How to install:
Go to Android Studio -> Preferences -> Plugins and hit Browse repositories..
Search for AndroidXmlSorter, install and restart your Android Studio. Go to your strings.xml file and hit Ctrl+L. Voila.
Disclaimer: I'm not the author of this plugin, I just found it by chance and I think all the credits should go to the plugin author. The repo is here: https://github.com/roana0229/android-xml-sorter
For anyone else who bumps into this. Copy all the string elements, paste into an Excel spreadsheet sort A-Z and then copy and paste back.
[Sort Android strings.xml in Alphabetical Order]
There is a plugin called Lines Sorter which can sort selected lines or whole files.
2022-09 | Simple plugin free solution:
Android studio includes option to sort lines / reverse lines.
Highlight lines of code to be sorted
unsorted lines
Edit > sort lines or Edit > reverse lines
sort line
Enjoy (reverse) alphabetical order
sorted lines
Sadly AndroidXmlSorter doesn't work for me when sorting multi-line strings.
My solution: Sort the strings.xml according to my android_strings_format.xslt (with xsltproc) and reformat it (with xmllint).
Cons: You have to execute a script. Therefore, it is not a true native feature of Android Studio. But you can easily execute scripts in Android Studio.
The script:
#!/bin/sh
sort_xml_file() {
xsltproc --output "$1" android_strings_format.xslt "$1"
export XMLLINT_INDENT=" "
xmllint --format --encode "utf-8" --output "$1" "$1"
}
sort_xml_file "src/main/res/values/strings.xml"
The android_strings_format.xslt file:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
method="xml"
version="1.0"
encoding="UTF-8"
indent="yes"
omit-xml-declaration="yes"/>
<xsl:template match="/resources">
<resources>
<xsl:for-each select="string">
<xsl:sort select="#name"/>
<string name="{#name}">
<xsl:copy-of select="#* | node()"/>
</string>
</xsl:for-each>
</resources>
</xsl:template>
</xsl:stylesheet>
Works on Manjaro Linux x64.
EDIT: I have found a way to prevent multi-line text. I can enclose the text with quotes. <string name="available_version_error">"<u>ERRORa</u>"</string>
I used a XML formatter with an xslt definition - but this was too complex if you also uses plurals.
My solution: writing my own Python script:
import re
# add your files here
strings_files = ["path/to/strings.xml"]
# 1. transform the strings.xml file to a dict
# 2. sort the dict
# 3. transform the dict to a strings.xml file
def sort_strings_xml_file(path_to_file: str):
entries = dict()
current_entry_name = None
# read entries from strings.xml file
with open(path_to_file, "r") as file:
for line in file.readlines():
# a new entry was found in the strings.xml file
if line.strip().startswith("<string ") or line.strip().startswith("<plurals "):
current_entry_name = re.search(r'name="(.+)"', line).group(1)
entries[current_entry_name] = ""
# store content for the current entry
if current_entry_name is not None:
entries[current_entry_name] += line
# stop recording for the current entry
if line.strip().endswith("</string>") or line.strip().endswith("</plurals>"):
current_entry_name = None
entries = dict(sorted(entries.items()))
# write results back to the strings.xml file
with open(path_to_file, "w") as file:
file.write(('<?xml version="1.0" encoding="utf-8"?>'
'<resources>'
f'{"".join(entries.values())}</resources>'))
print(f"{path_to_file} was sorted")
for strings_file in strings_files:
sort_strings_xml_file(strings_file)
i would turn them to ASCII then sort that one and turn them back to string, very easy and very effective
Update: Easiest way is: Ctrl+A then Ctrl+Alt+L
For configuration: In Android studio, you can quickly sort XML code by following step:
Select all XML code in a file by Ctrl+A
Use combination: Ctrl+Alt+Shift+L
Select "Selected text" + "Rearrange code" Then Press RUN

While using sed command i receive the following error : Function cannot be parsed. Any Solutions or reason for this?

I need to replace a particular character in a text file with another character. For example, replacing "E" with "A":
Apple ice → ApplA Ica
While executing sed 's/E/A' < apple.txt > app.txt I receive the error
function cannot be parsed
Please help! I need to automate this using Antscript.
You should terminate your sed command with a slash (/) and I guess you want to exchange all occurences of E with A? Then you have to add a g for a global substitution:
sed 's/E/A/g' app.txt
sed 's/E/A/g' app.txt. You missed the trailing / (g means all occurrences),
Since you are in Ant environment, you probably don't need to execute sed at all, but rather use Copy task with filter, or ReplaceRegExp task.
<?xml version="1.0" encoding="UTF-8"?>
<project>
<replaceregexp file="apple.txt" flags="g" match="e" replace="A"/>
</project>
This alters the file in place:
$ cat apple.txt
Apple ice
$
$ ant
Buildfile: build.xml
BUILD SUCCESSFUL
Total time: 0 seconds
$
$ cat apple.txt
ApplA icA
Your example is strange with case (a|A, e|E). I'll assume that's typo.
Follow up: To declare encoding...
<?xml version="1.0" encoding="utf-8"?>
<project>
<replaceregexp file="apple.txt" encoding="utf-8" flags="g" match="Á" replace=" "/>
</project>
I tested this successfully. Before:
ApplA icA
ApplÁs icÁs
After:
ApplA icA
Appl s ic s

Resources