0

I have a test file called testPage with the following text:

|| '''Title1''' || '''Title2''' || '''Title3''' ||
|| Cell11 || Cell12 || Cell13 ||
|| Cell21 || Cell22 ||
|| Cell31 || Cell32 ||
|| Cell41 || Cell42 ||
|| CEll51 || Cell52 ||
|| Cell61 || Cell62 ||
|| Cell71 || Cell72 ||

That I want to look like:

{|
|'''Title1''' || '''Title2''' || '''Title3''' ||
|-
| Cell11 || Cell12 || Cell13 ||
|-
| Cell21 || Cell22 ||
|-
| Cell31 || Cell32 ||
|-
| Cell41 || Cell42 ||
|-
| CEll51 || Cell52 ||
|-
| Cell61 || Cell62 ||
|-
| Cell71 || Cell72
|}

I have a script:

#!/bin/bash

isTable=0
beginTable="^\|\|"
lineNum=1

while IFS= read -r line
do
    echo "lineNum: $lineNum, line: $line, isTable: $isTable"
    if [[ $line =~ $beginTable ]]
    then
        if [ "$isTable" -eq "0" ]
        then
            isTable=1
            sed -r $lineNum's_\|\|_\{\|\n\|_' -i testPage #Begin table
            echo "begin table"
        else
            sed -r $lineNum's_^\|\|_\|-\n\|_' -i testPage #Define row ##DOESN'T WORK##
            echo "start of row"
        fi
    else
        if [ "$isTable" -eq "1" ]
        then
            isTable=0
            sed -r $lineNum's_(.*)$_\1\n\|\}\n_' -i testPage #End table ##WEIRD RESULT##
            echo "end table"
        fi
    fi
((lineNum++))
done < testPage

That gives the result:

{|
| '''Title1''' || '''Title2''' || '''Title3''' ||
|-
| Cell11 || Cell12 || Cell13 ||
|-
| Cell21 || Cell22 ||
|-
| Cell31 || Cell32 ||
|| Cell41 || Cell42 ||
|}

|| CEll51 || Cell52 ||
|| Cell61 || Cell62 ||
|| Cell71 || Cell72 ||

I can't figure out why it stops substituting after three iterations even though the loop reports the appropriate line and line number as well as matching the appropriate logic.

Any help is appreciated.

For clarity, testPage is a portion of a larger file, so sed beginning and ending flags (i.e., doing different things on lines 1 and $) won't do for me.

5
  • 2
    This is probably related, but I'm not positive so I'll make it a comment. Modifying a file while you're iterating over it is almost always going to be problematic. You probably need to find a way to separate iterating over the file from modifying it Commented Aug 24, 2015 at 17:40
  • @EricRenouf Might be a good point. Beaunus, what happens if you replace sed [...] -i testPage with sed [...] testPage >> newfile and check newfile? Commented Aug 24, 2015 at 18:28
  • @EricRenouf you may be right I'm investigating other ways to go about doing this but ultimately I want to edit the original file. Commented Aug 24, 2015 at 19:10
  • @Fiximan this works but shows each iteration so I get a copy of testPage for each line that exists with the one line edited. Let me know if this doesn't make sense I'll try a bit harder to explain my result. Commented Aug 24, 2015 at 19:12
  • I get your point: use your replacements as in sed -n -r $lineNum's_\|\|_\{\|\n\|_p' then, i.e. suppress output (-n) and print the replaced line ( p in sed operation). newfile has the correct output then, you have found the source of your problem: The number of lines should not change while iterating over the lines of a file. Commented Aug 24, 2015 at 19:43

2 Answers 2

0
sed 's/||$/&\n|-/;s/^||/|/;1s/^/{|\n/;$s/-$/}/' file

Note \n is GNU sed only, thus should otherwise be

sed 's/||$/||\
|-/;s/^||/|/;1s/^/{|\
/;$s/-$/}/' file
3
  • I appreciate this. It does what I asked, but I didn't ask appropriately. Unfortunately, the testPage file text that I provided is a portion of a larger file thus the beginning and ending flags,'1s' and '$s', won't work for me. Commented Aug 24, 2015 at 19:06
  • well, if you know/can determine the integer numbers for start and end lines of your block (e.g. via grep -n and a sed on the output), you can put the expression in double quotes and use e.g. $start and $end in the code. Commented Aug 24, 2015 at 19:41
  • And use a range for the other replacements. Commented Aug 24, 2015 at 19:46
0

I used a combination answers to achieve my desired result.

#!/bin/bash

isTable=0
beginTable="^\|\|"
lineNum=1
tableCount=0

while IFS= read -r line #Print changes to temp file
do
    if [[ $line =~ $beginTable ]]
    then
        if [ "$isTable" -eq "0" ]
        then
            isTable=1
            ((tableCount++))
            > $1_$tableCount
            sed -n -r $lineNum's_^\|\|_\{\|\n\|_p' $1 >> $1_$tableCount #Begin table
            sed -r $lineNum's_^\|\|_@'$tableCount'@_' -i $1
        else
            sed -n -r $lineNum's_^\|\|_\|-\n\|_p' $1 >> $1_$tableCount #Define row
        fi
    else
        if [ "$isTable" -eq "1" ]
        then
            isTable=0
            sed -n -r $lineNum's_(.*)$_\1\|\}\n_p' $1 >> $1_$tableCount #End table
        fi
    fi
((lineNum++))
done < $1

for ((n=1;n<=$tableCount;n++))
do
    sed -e '/@'$n'@/r '$1'_'$n'' -e '/^@'$n'@/d;/^||/d' -i $1
    rm "$1"_"$n"
done

I print each table to a different numbered file and then sed read each of those into the original file.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.