LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   sed problem... (https://www.linuxquestions.org/questions/programming-9/sed-problem-552371/)

jong357 05-08-2007 03:35 PM

sed problem...
 
Hey all. I need a certain line to be printed from a file but am having troubles.

Code:

foo
bar
foo
bar
foo
bar
bar
bar

I need to print bar that comes after the last foo found. I'm trying to take baby steps and just change the last occurance of foo to foomark, but I can't get that far.

Code:

sed 's/\(.*\)foo/\1foomark/' test
After looking around on the web, the above command is _supposed_ to change the last occurance of foo but it changes all the foo's. If someone want's to point me in the right direction, that would be great. Better yet, how can I just print bar after the last foo found? ;)

nmh+linuxquestions.o 05-08-2007 04:39 PM

Sed usually works on one line at a time - replacing the first or last instance of a pattern means the first or last on each line of input.

pixellany 05-08-2007 04:52 PM

to know that it has found the last "foo", it has to go the end of the file. In addition, it has to remember where the last "foo" was, and then print the next line.

It seems like you will need a loop, with something like awk (gawk) reading one line at a time and with a counter tracking line numbers. When the loop exits, it can return the line number of the last "foo". Then increment this and use it to get the line you want.

jong357 05-08-2007 05:06 PM

Oh.. I must have misunderstood then. Hmm... I also thought awk would be better able to handle it.

I'll go ahead and post this because it's directly related to my problem. The reason I'm looking to use sed or something similar is because the below code doesn't tranfer my variable. I'm using a logging function to redirect output but I need my variable from blah2 to stick when I call blah1 (which actually checks PIPESTATUS to see if we are done or an error occured).

This is a "borrowed" logging facility, thus I don't quite understand how to restructure calling on blah2 so it'll export my variable yet retain it's functionality...

Code:

#!/bin/sh

blah1()
{
echo $variable
}

blah2()
{
variable=printme
}

{ blah2 3>&1 1>&2 2>&3 | tee "blah.err";} &>"blah.log"
#blah2
blah1


makyo 05-08-2007 08:48 PM

Hi.
Quote:

Originally Posted by jong357
I need to print bar that comes after the last foo found.

Sometimes old tools come in handy. The editor ed can go backwards, so if we have ed go to the last line, then search backwards for foo, then print from there to bar, we should have it. I added line numbers to your test file to show how it works.
Code:

#!/bin/sh

# @(#) s2      Demonstrate interactive editor ed script.

echo " Original file data1:"
cat data1

echo
echo " Running ed:"
ed data1 <<EOF
$
=
?foo
.,/bar/w data2
q
EOF

echo
echo " File data2:"
cat data2

exit 0

Producing:
Code:

% ./s2
 Original file data1:
foo 1
bar 2
foo 3
bar 4
foo 5
bar 6
bar 7
bar 8

 Running ed:
48
bar 8
8
foo 5
12

 File data2:
foo 5
bar 6

cheers, makyo

ghostdog74 05-08-2007 09:10 PM

here's an awk one, i don't know what you want to do after you found the first bar after foo, so i break it out.

Code:

awk ' /foo/ { c=NR; }
 {arr[NR]=$0 }
 END { 
        for ( i = c; i<=NR; i++ ) {
                if  ( arr[i] == "bar" ) {
                        print arr[i],i
                        break
                }
        }
 }' "file"


jong357 05-08-2007 11:16 PM

Thanks guys for the help.. The more I think about it, the more I realize this isn't the way to go. My script is small and compact and I really don't wan't to clutter it up by adding lot's of stuff for this one thing.

Going upstream to the source, my problem lies in the below script by having brackets wrapped around my function call.

This whole sed/ed/awk stuff is just to try and come up with $variable.... Which is already defined in 'blah2'. So...... If I can't figure out how to get this to work by modifying my blah2 call, then I'll just throw in the towel I suppose... Bummer. I do appreciate the help tremendously tho... As you can see, if you run this script, $variable doesn't get outputted... I do need to retain my redirects but the .err file is useless and could stand to go away.

So.. In short. echo $variable from blah1 while still silencing/redirecting output from blah2...
Code:

#!/bin/sh

blah1()
{
echo $variable
}

blah2()
{
variable=printme
}

{ blah2 3>&1 1>&2 2>&3 | tee "blah.err";} &>"blah.log"
#blah2
blah1


ghostdog74 05-08-2007 11:30 PM

Quote:

Originally Posted by jong357
Thanks guys for the help.. The more I think about it, the more I realize this isn't the way to go. My script is small and compact and I really don't wan't to clutter it up by adding lot's of stuff for this one thing.

Going upstream to the source, my problem lies in the below script by having brackets wrapped around my function call.

This whole sed/ed/awk stuff is just to try and come up with $variable.... Which is already defined in 'blah2'. So...... If I can't figure out how to get this to work by modifying my blah2 call, then I'll just throw in the towel I suppose... Bummer. I do appreciate the help tremendously tho... As you can see, if you run this script, $variable doesn't get outputted... I do need to retain my redirects but the .err file is useless and could stand to go away.

So.. In short. echo $variable from blah1 while still silencing/redirecting output from blah2...
Code:

#!/bin/sh

blah1()
{
echo $variable
}

blah2()
{
variable=printme
}

{ blah2 3>&1 1>&2 2>&3 | tee "blah.err";} &>"blah.log"
#blah2
blah1



somehow, you have to "return" the "variable" in blah2 back to the main script.
one way to do this is :
Code:

..
variable=printme
echo $variable
}


jong357 05-08-2007 11:44 PM

No that's not working.. Good idea tho.. I see what your saying.. What sort of confuses me is, that if you comment my blah2 call with the redirects and then just call it straight out, it works..

jong357 05-09-2007 12:08 AM

Code:

#!/bin/sh

blah1()
{
echo ${variable}-new
}

blah2()
{
variable=printme
}

{ blah2 && export $variable 3>&1 1>&2 2>&3 | tee "blah.err";} &>"blah.log"
blah1

That works... However... It ruins my error checking from within blah1... Not good.
Code:

blah1()
{
  for i in "${PIPESTATUS[@]}"
  do
    test $i != 0 && { echo $variable ; exit 1 ; }
  done
  echo "Successful!"
  return 0
}

I have another idea that's pretty hackish. We'll see. Thanks for getting the ball rolling!!! ;)

EDIT: Ughhhh.. Something wierd is going on.. My test script works but my actuall build script doesn't...

test.sh
Code:

#!/bin/sh

blah1()
{
  for i in "${PIPESTATUS[@]}"
  do
    test $i != 0 && { echo $variable ; exit 1 ; }
  done
  echo "Successful!"
  return 0
}

blah2()
{
variable=Failed
mv ficticious ficticious.null
}

{ blah2 && export $variable 3>&1 1>&2 2>&3 | tee "blah.err";} &>"blah.log"
blah1


igorc 05-09-2007 12:16 AM

Hi,

# sed -n '/foo/{n;p;}' somefile.txt | tail -1

exp: sed command gives you every first line after every foo and with tail you get the last one which is the one you want.

Cheers,

jong357 05-09-2007 12:27 AM

Quote:

Originally Posted by igorc
sed -n '/foo/{n;p;}' somefile.txt | tail -1

Nice... Exactally what I was after. A one-liner that's not obtrusive on my script. The output from that line contains $variable but I'll still need to pipe it to a couple sed -e to isolate $variable..

It's too bad I had to start messing around and get obsessed with my above post... ;) I'll tuck that sed away and use it when I'm utterly fed up with trying to figure out why my script doesn't work but the test case does...

Thanks guys for your help. It's very appreciated.


All times are GMT -5. The time now is 06:26 AM.