我有以下情况:
我有一个文本文件,我试图循环,所以我可以知道每一行是否与“.mp3”匹配,在这种情况下,这是一个:
12 Stones.mp3
randomfile.txt
Aclarion.mp3
ransomwebpage.html
Agents Of The Sun.mp3
randomvideo.mp4
所以,我编写了以下脚本来处理它:
while read line || [ -n "$line" ]
do
varline=$(awk '/.mp3/{print "yes";next}{print "no"}')
echo $varline
if [ "$varline" == "yes" ]; then
some-command
else
some-command
fi
done < file.txt
预期的产出是:
yes
no
yes
no
yes
no
相反,它似乎错过了第一行,我得到以下内容:
no
yes
no
yes
no
你真的不需要使用Awk来进行简单的模式匹配,如果这就是你所使用的。
while IFS= read -r line; do
case $line in
*.mp3) some-command;,
*) some-other-command;;
esac
done <file.txt
如果你因为其他原因而无论如何使用Awk,那么在shell循环中循环行是效率低下的,并且通常是反模式。这并没有真正解决这个问题,但至少避免在每次迭代时执行新的Awk实例:
awk '{ print ($0 ~ /\.mp3$/) ? "yes" : no" }' file.txt |
while IFS= read -r whether; do
case $whether in
'yes') some-command ;;
'no') some-other-command;;
esac
done
如果你也需要"$line"
的内容,那么从Awk打印它并读取两个不同的变量是一个微不足道的变化。
我简化了read
表达式,假设您可以确保输入文件是单独格式良好的。如果你不能这样做,你需要在文件的最后一行放回更复杂的防范,以防丢失的换行符。
使用awk
$ awk '{if ($0 ~ /mp3/) {print "yes"} else {print "no"}}' file.txt
yes
no
yes
no
yes
no
或者更简洁:
$ awk '/mp3/{print "yes";next}{print "no"}' file.txt
$ awk '{print (/mp3/ ? "yes" : "no")}' file.txt
你忘记了什么吗?你的awk
没有明确的输入,改为:
while IFS= read -r read line || [ -n "$line" ]
do
varline=$(echo "$line" | awk '/.mp3/{print "yes";next}{print "no"}')
echo $varline
if [ "$varline" == "yes" ]; then
some-command
else
some-other-command
fi
done < file.txt
在这种情况下,您可能需要更改为/\.mp3$/
或/\.mp3[[:space:]]*$/
以进行精确匹配。
因为.
将匹配任何角色,所以例如/.mp3/
也将匹配Exmp3but.mp4
。
更新:将while read line
更改为while IFS= read -r read line
,以便在分配给变量时保持每行的内容不变。
而awk
部分可以改进为:
awk '{print $0~/\.mp3$/ ? "yes":"no"}'
所以只使用awk
,你可以这样做:
awk '{print $0~/\.mp3$/ ? "yes":"no"}' file.txt
或者,如果您的目的只是if结构中的命令,那么您可以这样做:
awk '/\.mp3$/{system("some-command");next}{system("some-other-command");}' file.txt
或这个:
awk '{system($0~/\.mp3$/ ? "some-command" : "some-other-command")}' file.txt