Reputation: 110203
I need to delete two blocks of text from multiple files. The two blocks are:
<sales_end_date>None</sales_end_date>
... some text
<unavailable_for_vod_date>None</unavailable_for_vod_date>
How would I properly do the equivalent of:
find ./ -type f -name 'xml' -exec sed -i
'**remove <sales_end_date>None</sales_end_date>' {} \;
Upvotes: 2
Views: 1144
Reputation: 1875
Remove a block of code from multiple files in C#
I needed to remove a block of code from multiple files. I had problems with Swedish characters in a core project, so I needed to install System.Text.CodePagesEncodingProvider nuget package and use System.Text.Encoding.GetEncoding(1252) instead of System.Text.Encoding.UTF8.
public static void Main(string[] args)
{
try
{
var dir = @"C:\Test";
//Get all html and htm files
var files = DirSearch(dir);
foreach (var file in files)
{
RmCode(file);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
}
private static void RmCode(string file)
{
string tempFile = Path.GetTempFileName();
using (var sr = new StreamReader(file, Encoding.UTF8))
using (var sw = new StreamWriter(new FileStream(tempFile, FileMode.Open, FileAccess.ReadWrite), Encoding.UTF8))
{
string line;
var startOfBadCode = "<div>";
var endOfBadCode = "</div>";
var deleteLine = false;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains(startOfBadCode))
{
deleteLine = true;
}
if (!deleteLine)
{
sw.WriteLine(line);
}
if (line.Contains(endOfBadCode))
{
deleteLine = false;
}
}
}
File.Delete(file);
File.Move(tempFile, file);
}
private static List<String> DirSearch(string sDir)
{
List<String> files = new List<String>();
try
{
foreach (string f in Directory.GetFiles(sDir))
{
files.Add(f);
}
foreach (string d in Directory.GetDirectories(sDir))
{
files.AddRange(DirSearch(d));
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
return files.Where(s => s.EndsWith(".htm") || s.EndsWith(".html")).ToList();
}
Upvotes: 0
Reputation: 14458
If you are luck, try this:
find -type f -name '*.xml' -exec sh -c \
'grep -v "<sales_end_date>None</sales_end_date>" "{}" >/tmp/a; mv /tmp/a "{}"' \;
Notice: This command is only useful to remove entire lines, not some chars in a line.
You can make a little helper script process.sh
to make your life easier:
#!/bin/bash
file="$1"
shift
tmp=`tempfile`
"$@" "$file" > $tmp
mv $tmp > "$file"
And then,
find -type f -name "*.xml" -exec process.sh {} grep -v "<sales_end_date>None</sales_end_date>" \;
Upvotes: 0
Reputation: 14183
xml ed -d "*/sales_end_date[text()='None']" -d "*/unavailable_for_vod_date[text()='None']" your-input.xml
Example: Assuming your xml looks like this:
<here>
<top_level>
<something>1</something>
<sales_end_date>None</sales_end_date>
<unavailable_for_vod_date>None</unavailable_for_vod_date>
</top_level>
</here>
Will output:
<here>
<top_level>
<something>1</something>
</top_level>
</here>
Upvotes: 1
Reputation: 43673
If None is inside of just those tags you want to remove, then you can use:
find . -name *.xml | xargs sed -ri 's/<.*?>None<.*?>//g'
Upvotes: 0
Reputation: 212248
I think you are looking for:
find . -type f -name '*.xml' -exec sed -i \
-e '\@^<sales_end_date>None</sales_end_date>@d' \
-e '\@^<unavailable_for_vod_date>None</unavailable_for_vod_date>@d' {} \;
But I wouldn't call this doing it properly. The -i
option to sed is arguably never proper to use at all, and parsing xml with sed is rightly considered an abomination. However, this should do the job.
Upvotes: 1
Reputation: 656
I can't test this right now because I don't have a bash command shell, but sed 's/before/after/g'
is the foundation of what you're looking for. I've often done this with a bit of piping
#!/bin/bash
before_string1='<sales_end_date>None</sales_end_date>'
after_string1=''
before_string2='<unavailable_for_vod_date>None</unavailable_for_vod_date>'
for file in `find ./ -type f -name 'xml'`; do
cat ${file} | sed "s/$before_string1/${after_string1}/g" > ${file}.tmp1
cat ${file}.tmp1 | sed "s/$before_string2/${after_string2}/g" > ${file}.tmp2
mv ${file.tmp2} ${file}
rm -f ${file.tmp1}
done
You'll have to make sure none of your before or after strings use /
or else you'll need to escape them, but I'm sure you have the bash scripting and sed skills for that.
Upvotes: 0