Bash脚本跳转到else语句,然后不跳转,没有显示任何错误



我创建了一个脚本,它应该读取一个文件,然后找出第一行的第一个单词/行中是否有元音,如果有,它应该只输出列表中的前10个单词。如果不是第一个15。我的问题是,当我输入一个以元音开头的文件时,脚本没有显示前10行,而是显示前15行,无论它是否以元音开头。

我的脚本如下:

首先读取文件,然后将第一个单词放入变量中,然后检查它是否以元音开头,然后输出到另一个文件中。

#!/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 

我的剧本没有承认当时的说法,也不确定为什么。

f.ex输入文件:file.txt岛公共汽车马车火车拖拉机

我试着把2行中的==改成=~。我试着去掉了,另一个头-15,看看我是否得到了前10行。还有拼写检查,jdoodle显示没有错误

问题1

通过将赋值放到管道中,可以在子shell中运行它。变量值不会从子shell传播到父进程。

解决方案

# cat file.txt | word=$(head -1 file.txt)
word=$(head -1 file.txt)

此外,这将读取变量中的第一个,而不是第一个。要删除第一个空格后的所有内容,可以使用参数扩展:

word=${word%% *}  # Remove everything from the first space onward.

问题2

==运算符需要在右侧显示一个模式,而不是正则表达式。如果使用=~,则需要正则表达式,引号强制执行字面含义。

解决方案

# if [[ "$word" == '^[AaEeIiOoUu]' ]]
if [[ $word == [AaEeIiOoUu]* ]]
# or
if [[ $word =~ ^[AaEeIiOoUu] ]]

此外,如果您想测试该行是否包含vowerl,而不是元音开头,则必须在模式前加一个星号,或者从正则表达式中删除插入符号:

if [[ $word == *[AaEeIiOoUu]* ]]
# or
if [[ $word =~ [AaEeIiOoUu] ]]

最小修复看起来像

#!/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 

尽管您可能想要重构到

if [[ "$(head -1 file.txt)" =~ [AaEeIiOoUu] ]]; then
lines=10
else
lines=15
fi
head -n "$lines" file.txt >words.txt

甚至在Awk:中重写整个内容

awk 'FNR == 1 { end = ($1 ~ /[AaEeIiOoUu]/ ? 10 : 15) } 1
FNR==end { exit }' file >words.txt

你的问题似乎意味着第一行只包含一个单词。如果您真的想只关注行中的第一个单词,那么shell脚本需要有一个稍微复杂一点的regex。

最新更新