1

BIG EDIT for a better understanding: is there a possibility in bash to put my output (lines) to columns in csv files (regarding the following challenge).

my script:

#!/bin/bash

## get ports, status, vlan

devices=`ls *.txt`

for device in $devices
do
        output=`echo $device | awk -F"." {'print $1'}`
        echo "Port;Status;VLAN\r" > $output".csv"

        port=`cat $device | awk 'BEGIN {OFS=";"}; /Fa[0-9]|Gi[0-9]|Te[0-9]/ && /disabled|connected/ {print $1}'`
        stat=`cat $device | awk 'BEGIN {OFS=";"}; /Fa[0-9]|Gi[0-9]|Te[0-9]/ && /disabled|connected/ {print $0}' | awk 'match($0,"connected|disabled.*"){print substr($0,RSTART)}' | awk '{print $1}'`
        vlan=`cat $device | awk 'BEGIN {OFS=";"}; /Fa[0-9]|Gi[0-9]|Te[0-9]/ && /disabled|connected/ {print $0}' | awk 'match($0,"connected|disabled.*"){print substr($0,RSTART)}' | awk '{print $2}'`


        var=$(paste -d, <(echo "$port") <(echo "$stat") <(echo "$vlan"))
        echo "$var" >> output."csv"
done

.

<input-file.txt>
Port      Name               Status       Vlan       Duplex  Speed Type
Fa0/1                        disabled     1            auto   auto 10/100BaseTX
Fa0/2                        disabled     1            auto   auto 10/100BaseTX
Fa0/3                        disabled     1            auto   auto 10/100BaseTX
Fa0/4                        disabled     1            auto   auto 10/100BaseTX
Fa0/5                        disabled     1            auto   auto 10/100BaseTX
Fa0/6                        disabled     1            auto   auto 10/100BaseTX
Fa0/7                        disabled     1            auto   auto 10/100BaseTX
Fa0/8                        disabled     1            auto   auto 10/100BaseTX
Fa0/9                        disabled     1            auto   auto 10/100BaseTX
Fa0/10    xxxx-xxx-xxx 0004. connected    3            full    100 10/100BaseTX
Fa0/11    xxxx-xxx-xxx bge0  connected    3          a-full  a-100 10/100BaseTX
Fa0/12    xxxx-xxx-xxx iLO   connected    2          a-full  a-100 10/100BaseTX
Fa0/13    xxxx-xxx-xxx bge0  connected    2          a-full  a-100 10/100BaseTX
Fa0/14                       disabled     1            auto   auto 10/100BaseTX
Fa0/15    xxxx-xxx-vpn bge0  connected    4          a-full  a-100 10/100BaseTX
Fa0/16    xxxx-xxx-vpn ilO   connected    2          a-full  a-100 10/100BaseTX
Fa0/17    xxxx-xxx xx.xx.xx. connected    2          a-full  a-100 10/100BaseTX
Fa0/18    xxxxxx-xxx1        connected    2          a-full  a-100 10/100BaseTX
Fa0/19                       disabled     1            auto   auto 10/100BaseTX
Fa0/20                       disabled     1            auto   auto 10/100BaseTX
Fa0/21    xxxxx-xxxxx        disabled     1            auto   auto 10/100BaseTX
Fa0/22    xxxxxx-xxx         disabled     1            auto   auto 10/100BaseTX
Fa0/23    xxxx-xxx           disabled     2            auto   auto 10/100BaseTX
Fa0/24    xxxxxx-xxxx        disabled     1            auto   auto 10/100BaseTX
Fa0/25                       disabled     1            auto   auto 10/100BaseTX
Fa0/26                       disabled     1            auto   auto 10/100BaseTX
Fa0/27                       disabled     1            auto   auto 10/100BaseTX
Fa0/28                       disabled     1            auto   auto 10/100BaseTX
Fa0/29                       disabled     1            auto   auto 10/100BaseTX
Fa0/30                       disabled     1            auto   auto 10/100BaseTX
Fa0/31                       disabled     1            auto   auto 10/100BaseTX
Fa0/32                       disabled     1            auto   auto 10/100BaseTX
Fa0/33                       disabled     1            auto   auto 10/100BaseTX
Fa0/34                       disabled     1            auto   auto 10/100BaseTX
Fa0/35                       disabled     1            auto   auto 10/100BaseTX
Fa0/36                       disabled     1            auto   auto 10/100BaseTX
Fa0/37                       disabled     1            auto   auto 10/100BaseTX
Fa0/38                       disabled     1            auto   auto 10/100BaseTX
Fa0/39                       disabled     1            auto   auto 10/100BaseTX
Fa0/40                       disabled     1            auto   auto 10/100BaseTX
Fa0/41                       disabled     1            auto   auto 10/100BaseTX
Fa0/42                       disabled     1            auto   auto 10/100BaseTX
Fa0/43                       disabled     1            auto   auto 10/100BaseTX
Fa0/44                       disabled     1            auto   auto 10/100BaseTX
Fa0/45                       disabled     1            auto   auto 10/100BaseTX
Fa0/46                       disabled     1            auto   auto 10/100BaseTX
Fa0/47                       disabled     1            auto   auto 10/100BaseTX
Fa0/48                       disabled     1            auto   auto 10/100BaseTX
Gi0/1     Xxxxxxxx Xxxxx xx  connected    trunk      a-full a-1000 10/100/1000BaseTX SFP
Gi0/2     Xxxxx xxxxxxx Xxx  connected    trunk      a-full a-1000 1000BaseSX SFP
Gi0/3                        disabled     1            auto   auto Not Present
Gi0/4                        disabled     1            auto   auto Not Present

result of script output should be:

<output.csv>
| Port   | Status    | VLAN |
| Fa0/1  | disabled  |  1   |
| Fa0/2  | disabled  |  1   |
| Fa0/3  | disabled  |  1   |
| Fa0/4  | disabled  |  1   |
| Fa0/5  | disabled  |  1   |
| Fa0/6  | disabled  |  1   |
| Fa0/7  | disabled  |  1   |
| Fa0/8  | disabled  |  1   |
| Fa0/9  | disabled  |  1   |
| Fa0/10 | connected |  3   |
and so on

Issue: after trying the "paste" command (thanks guys) .. i'm getting the following error: Syntax error: "(" unexpected

5
  • It would be useful if you included a short sample of one of the .txt files in the question. Commented Sep 11, 2014 at 16:08
  • It would be more useful to put a short sample of your input data in the question and show the corresponding desired output. You can also remove the output of your individual awk commands from the question. Commented Sep 11, 2014 at 18:15
  • thanks for ur hint, never used FIELDWIDTHS before, but the mentioned input file shows only 1/10 of the whole config file content. because the output of different queries seems to have the same structure. thus, there are more matches for "10 19 13 11", even after expanding the FW query - and yes, i'm using gnu awk 4 Commented Sep 12, 2014 at 8:20
  • i did a workaround to fix my "syntax" issue... by writing the output of my queries to files and afterwards doing "paste f1 f2 f3" ... works perfectly. solved! Commented Sep 12, 2014 at 9:13
  • indeed, i did!! :) thank you very much!! Commented Sep 12, 2014 at 9:35

2 Answers 2

5

Assuming you have GNU awk, the lines inside your loop can be compressed to something like this:

awk 'BEGIN{FIELDWIDTHS = "10 18 13 11"}{printf "| %s | %s | %s |\n", $1,$3,$4}' "$device"

If you have a different awk, the command will be more complicated but it is still possible to do what you want in one awk statement.

Some points on your attempt:

  • Make sure you put quotes around variables in your script (use "$details" instead of $details), as this protects you from a whole class of bugs caused by spaces in file names.
  • You don't need to use cat to pass the content of a file to awk. It's rare that you need to use cat for this kind of thing in general, as most programs accept the name of a file in their arguments. If they don't, you can always use program < filename rather than cat filename | program.
  • The use of ls is redundant (and possibly prone to bugs caused by files with awkward names). It would be much better to use for device in *.txt; do ...`

As a final point, be wary of getting trapped into thinking of one solution to your problem then asking how to implement it. It is much easier for others to come up with the best solution to the more general problem, based on their experience of various tools. In this case, the final answer is very different to the answer to your original question! I've left it below for now.

Let me know if you don't have GNU awk and I'll update my answer.


I think that you might be looking for the paste command

paste file.txt anotherf.txt

By default, the two files will be separated by a tab character. To use something else, you can specify the -d switch, for example -d, would set the separator to a comma instead.

If you want only the first columns from each file, you can use paste with awk:

paste -d, <(awk '{print $1}' file.txt) <(awk '{print $1}' anotherf.txt)

Assuming that the columns in your two files are separated by a simple delimiter (like a space), cut would work too:

paste -d, <(cut -f1 -d' ' file.txt) <(cut -f1 -d' ' anotherf.txt)

In light of the update to your question, if you already have the content inside two variables, you can use this command instead:

paste -d, <(echo "$var1") <(echo "$var2")

Thanks to all who contributed in the comments.

Sign up to request clarification or add additional context in comments.

8 Comments

Probably paste <(awk '{print $1}' f1) <(awk '{print $1}' f2)
or ;) paste -d, <(cut -f1 -d' ' f1) <(cut -f1 -d' ' f2)
As per the new requirement of the OP, paste <(echo "$var1") <(echo "$var2") should make. Btw, I already +1, but get a virtual +1 again for patience on improving the answer!
thanks! but still got an issue: Syntax error: "(" unexpected
@jayFour Perhaps it would be helpful to show a sample of what the variables contain in the question. Also, try enabling debugging with set -x.
|
1

You can use the getline function in awk to read from a separate file and synchronize the fields:

$ awk 'getline line<ARGV[2]{split(line,a)}NR==FNR{print $1,a[1]}' file.txt anotherf.txt
1 one
2 two
3 three
4 four
5 five

1 Comment

Some useful material indeed, thanks. After reading it, I think my usage of getline seems to be appropriate :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.