Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

A good mate on a forum had helped me with creating this script but everything Ive thrown at it outputs wrong and I do not know why or what is the issue. I ran all my script in ubuntu's terminal if questioned as bash test.sh.

My goal is to increment several .xml file's process></process> tags, but some files could have 1 to 100 tags.

Example:

 - jfksaJDFH
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - jdhkjasdh
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>

After script:

 - jfksaJDFH
 - <process>value="1"</process>
 - <process>value="2"</process>
 - <process>value="3"</process>
 - <process>value="4"</process>
 - jdhkjasdh
 - <process>value="5"</process>
 - <process>value="6"</process>
 - <process>value="7"</process>
 - <process>value="8"</process>

Script:

#!/bin/bash

dir="/mnt/Desktop/test/"

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '<process></process>' ]]; then
           echo "<process>value=\"$((i++))\"</process>"
        else
           echo "$line"
        fi
    done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)

when script above is ran removes last <process>value=""</process>

modify script to this:

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '<process></process>' ]]; then
           echo "$line"
        else
           echo "<process>value=\"$((i++))\"</process>"
        fi
    done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)

Output of file is this:

<process>value="1"</process>
<process>value="2"</process>
<process>value="3"</process>
<process>value="4"</process>
<process>value="5"</process>
<process>value="6"</process>
<process>value="7"</process>
<process>value="8"</process>
<process>value="9"</process>
<process>value="10"</process>
<process>value="11"</process>
<process>value="12"</process>
<process>value="13"</process>
<process>value="14"</process>
<process>value="15"</process>
<process>value="16"</process>
<process>value="17"</process>
<process>value="18"</process>
<process>value="19"</process>
<process>value="20"</process>
<process>value="21"</process>
<process>value="22"</process>
<process>value="23"</process>

which in other words increments but removes all other content in the page.

share|improve this question

2 Answers 2

up vote 1 down vote accepted

put this script in a file (ex: 'increase.awk') :

BEGIN { i = 1 }
/.*<process>value=""<\/process>.*/ { split($0, a, "value=\"\"") ; print a[1] "value=\"" i++ "\"" a[2] ; next }
/.*/ { print $0 }

and then call:

gawk -f increase.awk < yourinputfile

explanation: in awk, split("string", a, "separatorstring") splits the "string" into an array called a, using "separatorstring" as separator. So a[1] contains everything until the 1st "separatorstring", then a[2] contains everything until end of line or until the next "separatorstring", etc.

share|improve this answer
    
of course you'll need to edit this if some lines of the file you're trying to edit could contain parts of the strings used to discover where to insert the counter... (ex: can your script contain commented-out lines with such strings?) –  Olivier Dulac Dec 8 '12 at 1:38
    
and your example assumed that there is only one of those on a line, but if you need to have more complicated cases, you can simply pre-treat the file to temporarily have one per lines, then put the lines back together if needed. (for this, prepend and append the <process...../process> with "begin" and "end", and put newlines before and after those, and revert once this new file has been edited by the awk script. –  Olivier Dulac Dec 8 '12 at 1:48

Have you noticed, you have reverted the if-then-else construct's logic when you rewote the script

please note the placement of lines commented with line1 and line2 below. You had them reversed in your re-written code

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '' ]]; then
           echo "value=\"$((i++))\""   # line 1 ***************
        else
           echo "$line"                # line 2 ***************
        fi
    done 3 "$file.xml"
done 

hope this helps

share|improve this answer
    
Yes I am very aware of this. If you read below the sample script it says that when it is ran it deletes the last tag. –  Matt Dec 10 '12 at 17:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.