Concatenate SH command results on a line

Asked

Viewed 1,498 times

3

I’m starting to learn Shell Script and I have a question. I’m creating a .sh to take the number of processes running in the OS and export this information in a file .csv. The problem is that I would like to save the results all in one line.

Exemplo atual:

    DATA
    PROC1
    PROC2

Expected:

DATA PROC1 PROC2

Script:

#!/bin/bash
date +"%Y-%m-%d %H:%M" >> /home/dsadm/LogProcessos/psResults.csv
ps -ef | grep osh | wc -l >> /home/dsadm/LogProcessos/psResults.csv
ps -ef | wc -l >> /home/dsadm/LogProcessos/psResults.csv

2 answers

5


There are many ways, that’s one:

echo `date +"%Y-%m-%d %H:%M"` \; `ps -ef | grep osh | wc -l` \; `ps -ef | wc -l` >> log.csv

Everything that comes between backticks is executed by the shell, as if the result had been typed in place of the command.

To separate the columns, I used the exhaust \ before the ; not to be interpreted as command line splitter

2

An alternative is to use awk with the command printf, since it prints the content of each line, but without adding the line break:

awk '{printf $0 " ";}' psResults.csv

With this all the lines of the file are united to stay all in one line, separated by space. To do everything in the script, I suggest creating the data in a temporary file and only at the end play the output of awk in the file you need:

#!/bin/bash

# Faz o que precisa no arquivo temporário
date +"%Y-%m-%d %H:%M" >> /tmp/results
ps -ef | grep osh | wc -l >> /tmp/results
ps -ef | wc -l >> /tmp/results

# awk joga tudo no arquivo final
awk '{printf $0 " ";}' /tmp/results >> /home/dsadm/LogProcessos/psResults.csv

# apaga o arquivo temporário
rm /tmp/results

I did it because if you do awk ... arquivo > arquivo it may overwrite the file and lose everything (and if do with >>, it adds the content at the end of the file). Using different files is more guaranteed.


Since this is a CSV file, you can change the command to put a comma (or semicolon) instead of the space:

# vírgula
awk '{printf $0 ",";}' /tmp/results

# ponto-e-vírgula
awk '{printf $0 ";";}' /tmp/results

The problem is that it leaves a comma at the end (DATA,PROC1,PROC2,). You can delete this by making a command a little more complex, to check if it is on the last line. Just use wc -l to count the lines of the file and put it in a variable, which will be used by awk:

# coloca vírgula entre os registros, exceto depois do último
awk -v last="$(wc -l < /tmp/results)" '{printf $0; if (NR != last) printf ","};' /tmp/results

With this, it only puts the comma if it is not the last record, resulting in DATA,PROC1,PROC2


Another alternative is to use sed:

sed -e :a  -e 'N;s/\n/ /;ta' psResults.csv 

The option N joins the current line with the next, and then s/\n/ / replaces line break by space. ta makes him make a loop for the label a, that was set at the beginning (:a). That is, it repeats this substitution process until the end of the file. In the end, all the lines are united in one, separated by space.

You can exchange comma, but you have the same problem of awk (puts a comma at the end).

  • 1

    Thank you very much!

  • 1

    @Don’t forget to choose one of the answers and accept it if it has solved your problem. See here how to do: https://pt.meta.stackoverflow.com/q/1078/112052

Browser other questions tagged

You are not signed in. Login or sign up in order to post.