2

on a POSIX shell, no Python and no awk available (so don't bother telling me I should use a "real" programming language) I have to loop through a csv file.

https://datacadamia.com/lang/bash/read

My initial guess was :

while IFS=";" read -r rec_name rec_version rec_license rec_origin rec_modification rec_newlicense
do
    if [ "$name" = "$rec_name" ]; then
        # if [ "$version" = "$rec_version" ]; then
            if [ "$license" = "$rec_license" ]; then
                license="$rec_newlicense"
            fi
        # fi
    fi
done < <(tail -n +2 "${output_file%%.*}.csv")

But the last line wasn't "posix" compliant. So I tried :

while IFS=";" read -r rec_name rec_version rec_license rec_origin rec_modification rec_newlicense
do
    if [ "$name" = "$rec_name" ]; then
        # if [ "$version" = "$rec_version" ]; then
            if [ "$license" = "$rec_license" ]; then
                license="$rec_newlicense"
            fi
        # fi
    fi
done < "${output_file%%.*}.csv"

That did the trick, somehow, but the header line was processed as well.

Another problem was that the fields 'rec_version', 'rec_origin' and 'rec_modification' weren't referenced.

How to ignore them ?

Because I also tried :

while IFS=";" read -r -a rec
do
    if [ "$name" = "${rec[0]}" ]; then
        # if [ "$version" = "${rec[1]}" ]; then
            if [ "$license" = "${rec[2]}" ]; then
                license="${rec[5]}"
            fi
        # fi
    fi
done < "${output_file%%.*}.csv"

But then I get :

read: line 93: illegal option -a

So, your take on this ?

Regards.

Kochise
  • 123
  • 1
    What system is this that has no awk? Awk is POSIX so it's really strange. Is this an embedded system? Does it also not have other basic tools like cut or perl or sed? – terdon Feb 16 '22 at 09:47
  • Embedded system indeed, but wasn't used to such a bare minimal, not even a decent bash that support arrays. – Kochise Feb 16 '22 at 10:25
  • And you don't even have perl? – terdon Feb 16 '22 at 10:26
  • /bin/sh: perl: not found – Kochise Feb 16 '22 at 10:28
  • What kind of embedded system, and why does it need to parse CSV… seems like a lot to ask such a stripped down thing. Just curious. Glad you already got an answer. – Zach Young Feb 27 '22 at 22:30

1 Answers1

2

Only <() is non-POSIX in your first try, so just use normal pipes instead:

tail -n +2 "${output_file%%.*}.csv" | 
  while IFS=";" read -r rec_name rec_version rec_license rec_origin rec_modification rec_newlicense
  do
    if [ "$name" = "$rec_name" ]; then
        if [ "$license" = "$rec_license" ]; then
            license="$rec_newlicense"
        fi
    fi
  done

That seems a bit complex though. I can't be sure since you don't show the data you're parsing, but I suspect you can do:

tail -n +2 "${output_file%%.*}.csv" | 
  while IFS=";" read -r rec_name rec_version rec_license rec_origin rec_modification rec_newlicense
  do
    if [ "$name" = "$rec_name" ] && [ "$license" = "$rec_license" ] 
    then
        license="$rec_newlicense"
    fi
  done

As for ignoring unused terms, I'm afraid you can't do that for terms that are in the middle. You can easily take the first N terms and ignore the rest with:

while read -r var1 var2 rest; do ... done

That will read the first 2 variables and save the rest of the line as rest. Unfortunately, if you need to use the last one, you will need to capture all of them. Alternatively, remove them before passing to the shell:

tail -n +2 "${output_file%%.*}.csv" | 
    cut -d';' -f1,3,6 | 
        while IFS=";" read -r rec_name rec_license  rec_newlicense
        do 
          if [ "$name" = "$rec_name" ] && [ "$license" = "$rec_license" ] 
          then
              license="$rec_newlicense"
          fi
        done
terdon
  • 242,166
  • Yeah, the csv file format is not my own and only a few fields are to be used, hence using discard placeholder would have been great, alas. Or using arrays. – Kochise Feb 16 '22 at 10:27
  • @Kochise don't you even have tools like cut? If you have tail, you should have cut. If so, you can do tail -n +2 "${output_file%%.*}.csv" | cut -d';' -f1,3,6 | while IFS=";" read -r rec_name rec_license rec_newlicense; do .... – terdon Feb 16 '22 at 10:39
  • That's the solution indeed, not very explicit but it did the job. Thank, if you modify your answer accordingly, I'll set it as the "one" :) – Kochise Feb 16 '22 at 11:30
  • Haven't linux considered a more capable bash or scripting language that doesn't require to fiddle with various commands for performing such simple task that should have been rendered user friendly long before ? And not having a MB load of python or perl or whatever else ? – Kochise Feb 16 '22 at 11:30
  • @Kochise answer updated. As for the rest, you are working on a system with arbitrarily imposed restrictions which lacks the basic POSIX toolset. Linux systems (i.e. GNU/Linux systems) come with very powerful tools but that isn't what you are using. You can't complain about limited capability when you are using a system that has been crippled by the exclusion of standard tools. And anyway, it doesn't really get more user friendly than cut -d';' -f1,3,6, what else do you need? – terdon Feb 16 '22 at 11:34
  • Also, more generally, shells are not good scripting languages. They're shells; they excel at scheduling commands to be run one after another, and have some rudimentary scripting capabilities, but they are not and should not be used as full programming languages, and they are a particularly bad choice for parsing text files as you're doing. So, basically, if you're using a screwdriver to hammer a nail, you don't get to complain that the screwdriver isn't as good as a hammer :). – terdon Feb 16 '22 at 11:45