netguy has asked for the wisdom of the Perl Monks concerning the following question:

I have written a script that will only ever run in a linux environment. The purpose of the script is to be piped to, look for certain strings and modify or not and send to STDOUT or not similar to grep/awk/sed but with a more specific purpose that those don't address easily.

I have looked though other posts, but didn't find anything. Not sure if that's because it's impossible, everyone else already knows but me or I just don't know how to search.

I'm trying to determine within the script the context in which it is being executed, and/or better yet, the process/command I'm receiving STDIN from. With my current script, if it runs as in the first example below, it just sits waiting for STDIN and won't exit without CTRL-C or some other non-graceful intervention. When it's receiving STDIN as in the second example, everything works as expected.

For Example:
  • [root@server ~]# script
  • or
  • [root@server ~]# cat myfile | script
  • This is an example of the script logic I'm trying to accomplish:

    #!/usr/bin/perl use strict; my @output; my $stuff; if ( <not piped to> and @ARGV == 0 ) { print "This is how you use this perl script...\n"; exit; } while (<STDIN>) { if ($_ =~ m/start/ ) { push @output, chomp; $stuff = 1; } elsif ( $_ =~ m/end/ ) { push @output, chomp; changout(@output); undef $stuff; } elsif ($stuff) { push @output, chomp; } else { print STDOUT $_; } } sub changout { foreach my $line (@_) { if ( $line =~ m/something/ ) { print STDOUT $line; } else { print STDOUT $line."\n"; } } }

    Replies are listed 'Best First'.
    Re: How do I Determine if my script is being piped to?
    by BrowserUk (Patriarch) on Nov 21, 2013 at 00:38 UTC

      Have you tried -p STDIN?


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Just tested -p and looks like that's just the opposite of -t. At least in my case that is the behavior.

        I guess my question was more on the side of I didn't know what to search for. The -p and -t operators can accomplish what I need. It's almost silly that the solution was staring me in the face and I didn't know it. During my many searches, I came across -p a couple times and maybe -t, but didn't have the instinct to look them up.

        Thanks again for the help.

        ooh thanks BrowserUk never eard of -p operator, or may be forgotten it long time ago.
        Due to my ignorance i wonder if -p -t are one the opposite of the other: in the docs -p is just mentioned and, albeit self explanatory, not described. There are cases where -t does not suffice, are also cases where -p does not suffice? edge cases?
        My test:
        perl -e " print -t STDIN ? qq(STDIN has tty) : qq(NO tty associated);p +rint ' - '; print -p STDIN ? qq(STDIN is a pipe or a named pipe) : qq +(NOT a pipe)" #out #STDIN has tty - NOT a pipe hostname | perl -e " print -t STDIN ? qq(STDIN has tty) : qq(NO tty as +sociated);print ' - '; print -p STDIN ? qq(STDIN is a pipe or a named + pipe) : qq(NOT a pipe)" #out #NO tty associated - STDIN is a pipe or anamed pipe
        thanks
        L*
        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
          There are cases where -t does not suffice, are also cases where -p does not suffice? edge cases?

          Search the stat() docs for S_IFIFO.


          With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
          Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
          "Science is about questioning the status quo. Questioning authority".
          In the absence of evidence, opinion is indistinguishable from prejudice.
    Re: How do I Determine if my script is being piped to?
    by kschwab (Vicar) on Nov 21, 2013 at 00:11 UTC
      You can tell if STDIN is a tty or not, which isn't quite the same thing, but it might suffice:
      #!/usr/bin/perl use POSIX qw(isatty); if (isatty(STDIN)) { die("nope. not like that\n"); } while (<>) { print "$_\n"; }

        Thanks much for the reply. I didn't expect an answer so fast or that it would provide the solution.

        Though the example you gave doesn't work, maybe because of 'use strict;' , I did find a couple things that do work. If I did have a better understanding of Linux, I may have found the answer on my own. Just something I'll have to work on.

        Here are a couple examples of what did work for me:
        use strict; if ( -t STDIN ) { print "This is what you're supposed to do ...\n"; exit; } # or use POSIX qw(isatty); if ( isatty(\*STDIN) ) { print "This is what you're supposed to do ...\n"; exit; } while (<STDIN>) { print STDOUT "Add something to STDOUT".$_; }

        Thanks for the help. It wasn't a show-stopping feature, just trying to mitigate confusion by some users when the command is run and the cursor just sits there doing nothing.

        Well, kschwab has a much better memory that I do. You can pretty much ignore what I was posting at the same time he was giving you the answer I was looking for. :)

        It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
    Re: How do I Determine if my script is being piped to?
    by boftx (Deacon) on Nov 21, 2013 at 00:13 UTC

      IIRC, there is in fact a way to tell if STDIN is connected to a tty. It might be a *nix system call. In fact, I recall doing this myself many, many moons ago for basically the same reason you are. I'd have to do some searching myself, but look for how to determine if a process is connected to a terminal instead of how to determine if STDIN is from a pipe, that will probably get you closer to finding an answer.

      It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
    Re: How do I Determine if my script is being piped to?
    by johngg (Canon) on Nov 21, 2013 at 12:38 UTC

      I have a script that does something like that. It deals with text and can read that text from a file if $ARGV[ 0 ] is a readable file, from @ARGV if present but not a file, from a piped command if there's something to read on STDIN or typed in if not. It uses IO::Select to determine if input is waiting to be read on STDIN and thereby makes the assumption that it is being piped to.

      use strict; use warnings; use IO::Select; ... my $text; if ( @ARGV ) { if ( -r $ARGV[ 0 ] ) { $text = do { local $/; <>; }; } else { $text = join q{ }, @ARGV; } } else { my $select = IO::Select->new(); $select->add( \ *STDIN ); print qq{Type text, finish with ctrl-D on its own line\n} unless $select->can_read( 0.05 ); $text = do { local $/; <>; }; } ... # Do something with $text

      I hope this is of use.

      Cheers,

      JohnGG

    Re: How do I Determine if my script is being piped to?
    by wazat (Monk) on Nov 22, 2013 at 04:21 UTC

      I am not answering your question because I wonder if you are asking the wrong question.

      In your first case you need to learn to intervene gracefully.

      You script is waiting for end of input, so tell it there is no more input.

      In a UNIX shell ctrl-D indicates end of file.