I've created a script that should read a file, then find out wether the first line has a vowel in the first word/line, and if it does, it should output only the first 10 words in the list. If not the first 15. My issue is that the script instead of showing the first 10 lines when I input a file that starts with a vowel, it shows me the first 15 wether it's starts with a vowel or not.
My script is as following:
first reads file, then puts the first word in a variable to then be checked if it starts with a vowel, then outputs into another file.
#!/bin/bash
cat file.txt | word=$(head -1 file.txt)
if [[ "$word" == '^[AaEeIiOoUu]' ]]
then head -10 file.txt > words.txt
else head -15 file.txt > words.txt
fi
The then statement is not acknowledged by my script, unsure why.
f.ex input file: file.txt island bus carriage train tractor
I have tried changing the == in the 2 line to be =~. I have tried removing, the else head -15 to see if I get the first 10 lines. Also spellcheck, and jdoodle shows no errors
CodePudding user response:
Problem 1
By putting the assignment to a pipeline, you run it in a subshell. Variable values don't propagate form a subshell to the parent process.
Solution
# cat file.txt | word=$(head -1 file.txt)
word=$(head -1 file.txt)
Also, this reads the first line into the variable, not the first word. To remove everything after the first space, you can use Parameter Expansion:
word=${word%% *} # Remove everything from the first space onward.
Problem 2
The ==
operator expects a pattern on the right hand side, not a regex. If you use =~
, a regex is expected, but quotes enforce literal meaning.
Solution
# if [[ "$word" == '^[AaEeIiOoUu]' ]]
if [[ $word == [AaEeIiOoUu]* ]]
# or
if [[ $word =~ ^[AaEeIiOoUu] ]]
Moreover, if you want to test the line contains a vowerl rather than it starts with a vowel, you have to prepend an additional asterisk to the pattern, or remove the caret from the regex:
if [[ $word == *[AaEeIiOoUu]* ]]
# or
if [[ $word =~ [AaEeIiOoUu] ]]
CodePudding user response:
A minimal fix would look like
#!/bin/bash
# avoid doubly useless cat
word=$(head -1 file.txt)
# fix regex operator and regex
if [[ "$word" =~ [AaEeIiOoUu] ]]
then head -10 file.txt > words.txt
else head -15 file.txt > words.txt
fi
though you might want to refactor to
if [[ "$(head -1 file.txt)" =~ [AaEeIiOoUu] ]]; then
lines=10
else
lines=15
fi
head -n "$lines" file.txt >words.txt
or even rewrite the whole thing in Awk:
awk 'FNR == 1 { end = ($1 ~ /[AaEeIiOoUu]/ ? 10 : 15) } 1
FNR==end { exit }' file >words.txt
Your question seems to imply that the first line contains a single word. If you really want to focus on only the first word on the line, the shell script needs to have a slightly more elaborate regex.