我创建了一个脚本,它应该读取一个文件,然后找出第一行的第一个单词/行中是否有元音,如果有,它应该只输出列表中的前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。