5

I have a file named myfile.csv containing the following:

 abc:123:myname:1231
 def:423324:arbitrary:value:string
 StackExchange:Unix:Linux

From the terminal I run ./myscript.sh def

The contents of myscript.sh is:

#!/bin/bash
key_word_I_am_looking_for=$1
my_variable=`cat myfile.csv | awk -F: -v keyword="$key_word_I_am_looking_for" '( $1 == keyword )' END{print "$@" }'`
echo "$my_variable"

I want the code to search for the word def or any other word in the first parameter in the myfile.csv ie abc or StackExchange. Once found I would like it to take the whole line out without the seperators and place it in the my_variable variable, and echo it out to the terminal (so the output would look like: def 423324 arbitrary value string when ./myscript.sh def is entered to the terminal. When ./myscript.sh StackExchange the output would be StackExchange Unix Linux ).

Where am I going wrong? Is there an alternative?

4
  • 3
    grep 'def' myfile.csv | tr ':' ' '
    – Costas
    Apr 11, 2015 at 15:36
  • 1
    while IFS=':' read -r first a b c d e ; do [ "$first" = "$key_word_I_am_looking_for" ] && echo "$first $a $b $c $d $e" ; done < myfile.csv
    – Costas
    Apr 11, 2015 at 15:43
  • I like the 2nd, but instead of guessing how many fields there are, use read -a to use an array. Apr 11, 2015 at 15:44
  • @glennjackman Well, it is good idea.
    – Costas
    Apr 11, 2015 at 15:45

6 Answers 6

11

Your awk syntax is a little wrong.

#!/bin/bash
awk -F: -v keyword="$1" '$1 == keyword {$1=$1; print}' myfile.csv

The trick here is reassigning the value of one of the fields forces awk to recalculate $0 using the output file separator. Here, the default OFS is a space, so assigning the value of $1 to itself changes the colons to spaces.

A non-awk way to write this is:

grep "^$1:" myfile.csv | tr ":" " "

but that uses regular expression matching, not string equality

0
3

Here is a sed alternative:

sed -n '/^def:/s/:/ /gp' myfile.csv

If you pass the string as first positional parameter:

sed -n "/^$1:/s/:/ /gp" myfile.csv
0
0

Through python.

$ python -c "import sys;
with open(sys.argv[2]) as f:
    for line in f:
        if sys.argv[1] == line.split(':')[0]:
            print ' '.join(line.strip().split(':'))" def file
def 423324 arbitrary value string

Just run the above script on terminal with the search keyword as firs argument and the file-name as second argument.

0

Here is a solution using grep:

grep ^abc file | awk -F ":" '{print $1" " $2" " $3" " $4}'

1
  • 2
    I would’ve added more anchoring to the grep, such as a trailing colon. Also, the OP asked for the result to be in a variable.
    – Jeff Schaller
    Feb 21, 2018 at 11:39
0

Using Raku (formerly known as Perl_6)

raku -ne '.put if .=split(":")[0] eq "def";' myfile.csv

OUTPUT:

def 423324 arbitrary value string

Language notes: Perl-family languages utilize the concept of a 'topic'-variable. Raku extends and regularizes this concept (see Rosetta Code link below). Because routines now default to the $_ topic variable, a leading period is all that's needed to indicate action on the $_ topic variable. Writing out the above code 'longhand' you'd actually get:

raku -ne '$_.put if $_.=split(":")[0] eq "def";'

Finally, Raku offers a .= binary assignment operator, wherein essentially an interposed = (equal sign) is all that's needed to update the lvalue. Thus the code my $temp = $_.fn(…); $_ = $temp; can be compacted to $_.=fn(…) . Shorter...and no need to create a $temp temporary variable!

https://rosettacode.org/wiki/Topic_variable#Raku
https://docs.raku.org/routine/.=
https://raku.org/

0
#!/bin/bash
input=$1
awk -v input="$input" '$0 ~ input {gsub(":"," ",$0);print }' filename

example

 sh script.sh abc
abc 123 myname 1231

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .