Assigning system command's output to variable

前端 未结 6 1194
梦毁少年i
梦毁少年i 2020-11-28 04:55

I want to run the system command in an awk script and get its output stored in a variable. I\'ve been trying to do this, but the command\'s output always goes t

相关标签:
6条回答
  • 2020-11-28 05:35
    gawk '{dt=substr($4,2,11); gsub(/\//," ",dt); "date -d \""dt"\" +%s"|getline ts; print ts}'
    
    0 讨论(0)
  • 2020-11-28 05:40

    To run a system command in awk you can either use system() or cmd | getline.

    I prefer cmd | getline because it allows you to catch the value into a variable:

    $ awk 'BEGIN {"date" |  getline mydate; close("date"); print "returns", mydate}'
    returns Thu Jul 28 10:16:55 CEST 2016
    

    More generally, you can set the command into a variable:

    awk 'BEGIN {
           cmd = "date -j -f %s"
           cmd | getline mydate
           close(cmd)
         }'
    

    Note it is important to use close() to prevent getting a "makes too many open files" error if you have multiple results (thanks mateuscb for pointing this out in comments).


    Using system(), the command output is printed automatically and the value you can catch is its return code:

    $ awk 'BEGIN {d=system("date"); print "returns", d}'
    Thu Jul 28 10:16:12 CEST 2016
    returns 0
    $ awk 'BEGIN {d=system("ls -l asdfasdfasd"); print "returns", d}'
    ls: cannot access asdfasdfasd: No such file or directory
    returns 2
    
    0 讨论(0)
  • 2020-11-28 05:40

    You can use this when you need to process a grep output:

    echo "some/path/exex.c:some text" | awk -F: '{ "basename "$1"" |& getline $1; print $1 " ==> " $2}'
    

    option -F: tell awk to use : as field separator

    "basename "$1"" execute shell command basename on first field

    |& getline $1 reads output of previous shell command in substream

    output:
    exex.c ==> some text
    
    0 讨论(0)
  • 2020-11-28 05:45

    I am using macOS's awk and I also needed exit status of the command. So I extended @ghostdog74's solution to get the exit status too:

    Exit if non-zero exit status:

    cmd = <your command goes here>
    cmd = cmd" ; printf \"\n$?\""
    
    last_res = ""
    value = ""        
    
    while ( ( cmd | getline res ) > 0 ) {
    
        if (value == "") {
            value = last_res
        } else {
            value = value"\n"last_res
        }
    
        last_res = res
    }
    
    close(cmd)
    
    # Now `res` has the exit status of the command
    # and `value` has the complete output of command
    
    if (res != 0) {
        exit 1
    } else {
        print value
    }
    

    So basically I just changed cmd to print exit status of the command on a new line. After the execution of the above while loop, res would contain the exit status of the command and value would contain the complete output of the command.

    Honestly not a very neat way and I myself would like to know if there is some better way.

    0 讨论(0)
  • 2020-11-28 05:57

    Note: Coprocess is GNU awk specific. Anyway another alternative is using getline

    cmd = "strip "$1
    while ( ( cmd | getline result ) > 0 ) {
      print  result
    } 
    close(cmd)
    

    Calling close(cmd) will prevent awk to throw this error after a number of calls :

    fatal: cannot open pipe `…' (Too many open files)

    0 讨论(0)
  • 2020-11-28 05:59

    Figured out.

    We use awk's Two-way I/O

    {
      "strip $1" |& getline $1
    }
    

    passes $1 to strip and the getline takes output from strip back to $1

    0 讨论(0)
提交回复
热议问题