3

I have a text file that looks like this:

1923.12.312. Nikl
12391.123.123 Jo
12398123.123912 Ad

I am trying to loop through this file, and make 1923.12.312. variable1, and Nikl variable2 then use those in an echo command. Then it should continue and make 12391.123.123 variable1 and Jo variable2 and echo those etc.

So far, this is what I've done:

while read p
do 
variable1="$(awk '{print $1}')"
variable2="$(awk '{print $2}')"
echo "if [ \"\$STATUS\" == \"$variable1\" ]
then
vem=\"$variable2\"
fi"
done saker.txt

And that's supposed to put out:

if [ "$STATUS" == "1923.12.312." ]
then
vem="NIKL"
fi

etc. But it doesn't, instead, this is the output

awk: cmd. line:1: {print $2)
awk: cmd. line:1:          ^ syntax error
if [ "STATUS" == "12391.123.123
12398123.123912" ]
then
vem=""
fi

I also tried ditching the variables and did this instead:

while read p
do 
echo "if [ \"\$STATUS\" == \"`awk '{print $1}'`\" ]
then
vem=\"`awk '{print $2}'`\"
fi"
done saker.txt

But it produced the same result.

  • @don_crissti I didn't see that typo actually, but my last command doesn't have it, and it still doesn't work. while read was a recommendation from a stackoverflow user. What is better to use for processing text files then? (In your opinion) – DisplayName Dec 1 '15 at 1:31
  • @don_crissti Thanks, that did work. Why? To generate a script. The script I am using regularly needs to be updated with the information from saker.txt. – DisplayName Dec 1 '15 at 1:36
  • 1
    Related (and @DisplayName, please read this) : unix.stackexchange.com/a/169765/135943 – Wildcard Dec 1 '15 at 1:48
3

Using shell

If we use the ability of read to separate lines into variables and it is quite easy:

while read var1 var2
do
    echo "if [ \"\$status\" == \"$var1\" ]
then
vem=\"$var2\"
fi"
done <saker.txt

This produces:

if [ "$status" == "1923.12.312." ]
then
vem="Nikl"
fi
if [ "$status" == "12391.123.123" ]
then
vem="Jo"
fi
if [ "$status" == "12398123.123912" ]
then
vem="Ad"
fi

Using awk:

This awk command uses a single printf command:

$ awk '{printf "if [ \"$status\" == \"%s\" ]\nthen\nvem=\"%s\"\nfi\n",$1,$2}' saker.txt
if [ "$status" == "1923.12.312." ]
then
vem="Nikl"
fi
if [ "$status" == "12391.123.123" ]
then
vem="Jo"
fi
if [ "$status" == "12398123.123912" ]
then
vem="Ad"
fi
2

It is my STRONG suspicion that you shouldn't be running a script to update your script at all. Instead, you should just call awk from within your original script, and get the data you need that way. Then saker.txt could simply be used as a config file (which it is) to change the behavior of your script, (instead of using it to change the output of your script-making-script).

I have very limited data on your script, obviously, but what it looks like is that you are using saker.txt as a lookup table to set a variable in your script.

Specifically, the script snippet:

if [ "$STATUS" == "1923.12.312." ]
then
vem="Nikl"
fi
if [ "$STATUS" == "12391.123.123" ]
then
vem="Jo"
fi
if [ "$STATUS" == "12398123.123912" ]
then
vem="Ad"
fi

can be functionally reproduced with an inline awk script as follows:

vem=$( awk -v status="$STATUS" '$1 == status { printf "%s", $2 ; exit }' saker.txt )

This answers "How can I set a variable in bash based on looking up another variable's value in a file?" which is what it seems you're trying to accomplish by running your script-to-update-your-script.

There are caveats, of course, such as "What if the value of $STATUS isn't listed in saker.txt at all?" "What if it's listed twice?" "How can I set a default value for vem?" But you still have all those caveats, and moreso, with a script-updating-script.


EDIT: If you want to allow spaces in the value of vem as given in the saker.txt file, you're better off using something else for a delimiter, such as a tab:

$ cat saker.txt
1923.12.312.    Nikl
12391.123.123   Jo
12398123.123912 Ad

Then use the following version of the awk one-liner:

vem=$( awk -Ft -v status="$STATUS" '$1 == status { printf "%s", $2 ; exit }' saker.txt )

A caveat about tab delimiters: Be sure you don't use more than one tab. Unlike awk's default "whitespace delimited" handling, when you explicitly set the delimiter as a TAB only, each tab is counted as a delimiter regardless of whether there is any text between the tabs. So 10000<tab><tab>John will be regarded as THREE fields: "10000", "" (empty field), and "John".

  • I figured this out later. I am just running a script from there. Now my problem is that sometimes I need || because multiple $STATUS variables can match a single $vem, but that's another story. – DisplayName Dec 1 '15 at 2:34
  • I'm not sure I understand the bit about needing an OR operator. Do you mean that you might have multiple "status" numbers that associate to the same name? If so, why not just have multiple lines in the saker.txt file, one for each status? If you do it that way the awk one-liner above would work exactly the same. – Wildcard Dec 1 '15 at 2:56
  • Never mind, I thought wrong. – DisplayName Dec 1 '15 at 3:00
  • I tried a bunch of things but I couldn't get it to work with $STATUS including a space? (Should have specified that in question). – DisplayName Dec 1 '15 at 3:14
  • 1
    I'm quite curious by now what your script is doing with the value of vem after it's set, and where you get the value of STATUS from. :) – Wildcard Dec 1 '15 at 3:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.