sed command not working for me to change text in a file

UNIX gurus

I need your help with the following (The server is an AIX box).

I have a text file with the following information:

********************************************************
SOME LINES
case
:WORD1
SOME LINES
:WORD2
SOME LINES
:WORD3
SOME LINES
esac
SOME LINES
*********************************************************

I need to change the lines starting with : and replace them with *). For example:

********************************************************
SOME LINES
case
WORD1*)
SOME LINES
WORD2*)
SOME LINES
WORD3*)
SOME LINES
esac
SOME LINES
*********************************************************

I wrote the following code to get this done, but it's not working, only the last line gets changed, From :WORD3 to WORD3*), the other two (:WORD1 and :WORD2) don't get changed.

#!/bin/ksh
# ======================================
TWSDATADIR=/opt/apps/TWA/TWS/TWS
TWSDATAFILE=$TWSDATADIR/martin.ABEND
TWSTARGETFILE1=$TWSDATADIR/martin1.ABEND
TWSTARGETFILE2=$TWSDATADIR/martin2.ABEND
TWSTARGETFILE3=$TWSDATADIR/martin3.ABEND
# List the bad lines
# ===========================
sed -e '1,/case $JOBNAME/d' -e '/esac/,$d' $TWSDATAFILE |grep : > $TWSTARGETFILE1
BADLINES=`cat $TWSTARGETFILE1`
for line in $BADLINES
do
TEXT="*)"
good_line_temp=`echo $line | cut -d: -f2`
echo "Bad line: $line"
good_line=`echo "$good_line_temp$TEXT"`
echo "Good line: $good_line"
echo $good_line >> $TWSTARGETFILE3
# sed "s/$line/$good_line/g" $TWSDATAFILE
sed -e "s/${line}/${good_line}/g" $TWSDATAFILE > $TWSTARGETFILE2
done

*********************************************************
I believe the last "sed" command is missing something. Up to that point, the script works fine as shown below. However, when I change on the target file ($TWSTARGETFILE2) as explained above only the last occurrence (:WORD3) gets changed (to WORD3*), but not the 1st (:WORD1) or 2nd (:WORD) occurrence.

Bad line: :WORD1
Good line: WORD1*)
Bad line: :WORD2
Good line: WORD2*)
Bad line: :WORD3
Good line: WORD3*)

Thanks for your help on this.

Martin.

I believe this would more or less do what you require:

sed '/case/,/esac/{s/^:\(.*\)/\1*)/;}' file

But in order to turn it into shell case statement you also need to introduce proper indentation and closing ;; after every command list.

1 Like

Concur, but AIX- sed is a little bit peculiar about formatting programs:

sed '/case/,/esac/ {;s/^:\(.*\)/\1*)/;}' file

@thread-op:

Instead of this:

sed -e '1,/case $JOBNAME/d' -e '/esac/,$d' $TWSDATAFILE |grep : > $TWSTARGETFILE1
BADLINES=`cat $TWSTARGETFILE1`
for line in $BADLINES
do
[...]

This does the same with less effort (if you even need the intermediary file $TWSTARGETFILE1 as it is not used in the script at all - if you don't, remove the tee -command from the pipeline):

sed -n '/case/,/esac/ /^:/p' | tee $TWSTARGETFILE1 | while read line ; do
[...]

bakunin

Hi Bakunin,

Just tried it on AIX 7, but it did not seem to make a difference:

$ sed '/case/,/esac/{s/^:\(.*\)/\1*)/;}'  infile
********************************************************
SOME LINES
case
WORD1*)
SOME LINES
WORD2*)
SOME LINES
WORD3*)
SOME LINES
esac
SOME LINES
*********************************************************
$ sed '/case/,/esac/ {;s/^:\(.*\)/\1*)/;}' infile
********************************************************
SOME LINES
case
WORD1*)
SOME LINES
WORD2*)
SOME LINES
WORD3*)
SOME LINES
esac
SOME LINES
*********************************************************

hmm, interesting. Not long ago i had to change exactly this on some 6.1 system because sed refused to accept the command portion without a blank between the range-statements:

sed '/regexp/,/regexp/{ ...     # did not work
sed '/regexp/,/regexp/ { ...    # worked

As i encountered that peculiarity a few times (usually because of a typo, because i actively avoided that once i had this problem) i was of the impression the AIX- sed is just like this. I guess it has finally been fixed then. Btw. the same was true for negated clauses:

sed '/regexp/,/regexp/ ! { ...     # did not work, but works with GNU-sed
sed '/regexp/,/regexp/! { ...      # did also not work
sed '/regexp/,/regexp/ !{ ...      # worked

bakunin

First of all, thank you all for your replies and suggestions, unfortunately, it's still not working.

So far per your suggestions, I have tried these:

 sed '/case/,/esac/{s/^:\(.*\)/\1*)/;}' file
 sed '/case/,/esac/ {s/^:\(.*\)/\1*)/;}' file
 sed '/case/,/esac/ {;s/^:\(.*\)/\1*)/;}' file

So let me explain it easier:

I'm trying to go from this:

 case $JOBNAME in
  :WORD1
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=WARNING
    ;;
  :WORD2
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=MINOR
    ;;
  :WORD3
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=MINOR
    ;;
  *)
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=MINOR
    ;;
esac

=====================================================
to this:

 case $JOBNAME in
  WORD1*)
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=WARNING
    ;;
  WORD2*)
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=MINOR
    ;;
  WORD3*)
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=MINOR
    ;;
  *)
    APP="maestro-global"
    AG="prd-global-ssprodc"
    SERVICE="hcl hcl servers instance service"
    SEV=MINOR
    ;;
esac

============================================

Please help,

thanks,

curiousmal

None of the sed substitute command you are using can work because they are looking for a colon anchored at the start of a line (which would have been perfectly reasonable since you didn't use CODE tags and normal HTML text processing discards leading <space> and <tab> characters and coalesces all combinations of <space> and <tab> characters not at the start of a line into a single <space> character.

Try the following instead:

sed '/case/,/esac/ { s/^\([[:space:]]*\):\(.*\)/\1\2*)/; }' file

Thank you Don Cragun, the sed command with the space word in it worked, thank you for clarifying my mistakes as well.

Have a great week.

Martin