为什么我的变量在bash中没有保存它的值?

为什么我的变量在bash中没有保存它的值?,bash,Bash,我非常困惑 我编写了一个bash脚本,根据行中的子字符串将行排序为类别 下面是我的示例“lines.txt” 如果一行包含“line1”,则应将其排序为组“l1”。如果包含“line2”,则应将其归类为“l2”组 问题是保存类别的变量没有保留其值,我不知道为什么。这是剧本 #!/bin/bash categories="l1 l2" l1=" line1 " l2=" line2 " # match line1 cat lines.txt | while read flin

我非常困惑

我编写了一个bash脚本,根据行中的子字符串将行排序为类别

下面是我的示例“lines.txt”

如果一行包含“line1”,则应将其排序为组“l1”。如果包含“line2”,则应将其归类为“l2”组

问题是保存类别的变量没有保留其值,我不知道为什么。这是剧本

#!/bin/bash
categories="l1 l2"

l1="
    line1
"

l2="
    line2
"

# match line1
cat lines.txt | while read fline
do
    cate="no match"

    for c in $categories
    do
        echo "${!c}" | while read location
        do
            if [ ! -z "$location" ] && [[ "$fline" =~ "$location" ]]
            then
                echo "we are selecting category $c"
                cate="$c"
                break
            fi
        done

        if [ "$cate" != "no match" ]
        then
            echo "we found a match"
            break
        fi
    done

    echo "$cate:$fline"
done

exit 0
当我运行它时,我看到了输出

we are selecting category l1
no match:i am line1
we are selecting category l2
no match:i am line2
这意味着我们正在选择正确的组,但是当我们退出嵌套的“while”循环时,我们不记得它了


为什么我的变量没有保留它的值,我如何修复它?

由于管道的原因,while循环在子shell中执行。这意味着“cate”这个名称实际上是指两个不同的变量。一个在while循环外,另一个在子shell内的循环内。当子shell退出时,该值将丢失

解决这个问题的一种方法是使用这样的重定向

while read line; do
...
done < $myfile
读行时
;做
...
完成<$myfile
如果表达式更复杂,并且需要在子shell中执行某些操作,那么可以使用进程替换(感谢David Rankin提醒我这一点)

读取-r行时
;做
...

由于管道的原因,while循环在子shell中执行。这意味着“cate”这个名称实际上是指两个不同的变量。一个在while循环外,另一个在子shell内的循环内。当子shell退出时,该值将丢失

解决这个问题的一种方法是使用这样的重定向

while read line; do
...
done < $myfile
读行时
;做
...
完成<$myfile
如果表达式更复杂,并且需要在子shell中执行某些操作,那么可以使用进程替换(感谢David Rankin提醒我这一点)

读取-r行时
;做
...

done<当只需要一个简单的重定向来馈送
循环时,为什么仍然坚持使用here字符串和命令替换<代码>读取时-r行;做完成<$myfile
。不是
。。。done
“如果表达式更复杂,并且需要在子shell中执行某些操作,则……”
使用进程替换,例如在读取-r行时使用
;做done<@DavidC.Rankin这只是因为他最初的问题使用了cat,但我修改了我的答案,加入了重定向。好多了。你必须小心。否则,你(作为老师)将带着错误的想法开除学生。…。@DavidC.Rankin是的,我同意。谢谢你的帮助。遗憾的是,我们无法分享所回答问题的要点。当只需要一个简单的重定向来馈送
循环时,为什么仍然坚持使用here字符串和命令替换<代码>读取时-r行;做完成<$myfile
。不是
。。。done
“如果表达式更复杂,并且需要在子shell中执行某些操作,则……”
使用进程替换,例如在读取-r行时使用
;做done<@DavidC.Rankin这只是因为他最初的问题使用了cat,但我修改了我的答案,加入了重定向。好多了。你必须小心。否则,你(作为老师)将带着错误的想法开除学生。…。@DavidC.Rankin是的,我同意。谢谢你的帮助。很遗憾,人们不能分享所回答问题的要点。
while read -r line; do
...
done < <(find . -iname "*sh")