Sed save changes to same file in loop

I have got problems saving sed changes to the same file in a loop.
Basically I want the delimited value in every line of the file to be set to blank according to the value stored in var. var can be changed anytime.
I do not have sed -i and i've tried to mv the file. Any other ideas?

My file contents

31-JUL-10;31-JUL-10;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
31-JUL-10;31-JUL-10;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
31-JUL-10;31-JUL-10;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10

to

;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10

My code

var="1;2"
IFS=";"

    for i in $var
    do
        sed 's/[^;][^;]*;/;/$i' $file> $temp 
        mv $temp $file
    done

Hi.

You need double quotes around the sed, otherwise the shell won't expand $i.

Also, after deleting each field, you need to subtract 1 from other field numbers (what was field 2, after deleting field 1, will now be the new field 1).

And for it to work on the last field, you need either to modify the sed, or add a semi-colon to the end of the line:

$ cat sedTest
file=file1
temp=file1.out

var="1;6"
IFS=";"

X=0
for i in $var
do
  I=$((i - X))
  sed "s/$/;/;s/[^;][^;]*;/;/$I;s/;$//" $file> $temp 
  X=$((X + 1))
  mv $temp $file
done

cat $file

$ ./sedTest
;31-JUL-10;29-JUL-10;29-JUL-10;30-JUL-10;
;31-JUL-10;29-JUL-10;29-JUL-10;30-JUL-10;
;31-JUL-10;29-JUL-10;29-JUL-10;30-JUL-10;

$ # with var="1;2"

$ ./sedTest
$ ./sedTest
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10

you can try more simple :wink:

# justdoit
while read line
    do
     echo "$line" | sed 's/[^;]*;[0-9]*-[A-Z]*-[0-9]*;/;;/' >> temp
    done <file
     mv temp file ; more file
./justdoit
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10

I guess if the idea was to remove the first two fields, this would do:

$ sed -i.bak "s/[^;]*;[^;]*/;/" file
# or
$ sed "s/[^;]*;[^;]*/;/" file > temp && mv temp file

But I think the O/P wanted more flexibility than that.

yes, to clarify, i need the variable to store the position of the place that i need to be blank, not just the first 2 fields, of which scottn's example works beautifully. thanks.

Hi, your original idea seems sound to me except for the double quotes as scottn suggested, plus you need a revised regex syntax so that the operations are restricted to the intended fields:

var="1;2"
IFS=";" 
for i in $var
do
    sed "s/[^;]*;/;/$i" $file  > $temp  &&  mv $temp $file
done

output:

;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10

using var="1;3"

;31-JUL-10;;29-JUL-10;30-JUL-10;30-JUL-10
;31-JUL-10;;29-JUL-10;30-JUL-10;30-JUL-10
;31-JUL-10;;29-JUL-10;30-JUL-10;30-JUL-10

Another one with awk:

awk -v var="1;3" 'BEGIN{FS=OFS=";";split(var,a)} 
{
  for(i in a)$(a)=""
}
1' file > temp  &&  mv temp file

Use nawk or /usr/xpg4/bin/awk on Solaris if you get errors

I actually not understood what alienated wants ? :o
I understand now so wanted thing :slight_smile:

My method :wink:

#!/bin/bash
var=( "1" "2" )
val="[0-9]*-[A-Z]*-[0-9]*"
first=${var[0]}
end=$((${var[1]}-1))
sed "s/${val};/;/$first" file | sed "s/;${val};/;;/$end" > temp
      more temp
 
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10
;;29-JUL-10;29-JUL-10;30-JUL-10;30-JUL-10

when

 
var=( "1" "3" )

The output :slight_smile:

;31-JUL-10;29-JUL-10;;30-JUL-10;30-JUL-10
;31-JUL-10;29-JUL-10;;30-JUL-10;30-JUL-10
;31-JUL-10;29-JUL-10;;30-JUL-10;30-JUL-10

Portably avoiding the temp file shuffle with ed:

var=1\;2
IFS=\;
{ printf '1,$s/[^;]*;/;/%d\n' $var;  printf 'w\nq\n'; } | ed -s "$file"

or

var=1\;2
IFS=\;
ed -s "$file" <<EOED
$(printf '1,$s/[^;]*;/;/%d\n' $var)
w
q
EOED

Regards,
Alister