首页 > 解决方案 > 精炼 Bash 循环

问题描述

你好 Stackoverflow 社区,

请原谅我的天真,但我有一个基本的循环脚本运行一个更复杂的脚本,该脚本正在寻找一个文本文件以获取我作为数组的输入。我猜我让它工作了,但我知道这可以运行得更好、更自动化。

这是我的脚本查找的文本文件;

2014;14204;
2015;15042;
2015;15062;
...
end;

这是我作为循环运行的 bash 脚本;

{ while IFS=';' read  YEAR1 PROJ1 YEAR2 PROJ2 YEAR3 PROJ3 fake
    do 
        { echo "$YEAR1" | egrep '^#|^ *$' ; } > /dev/null && continue 
            $local/script.sh \
                --forinput1 $YEAR1/$PROJ1  \
                --forinput2 $YEAR2/$PROJ2  \
                --forinput3 $YEAR3/$PROJ3  \
    done 
} < textFile.txt

我自己做了一些研究,发现了一些我认为可行但无法正确实施的方法。如果您能给我一些建议,我将不胜感激。

编辑:我很抱歉,所以脚本确实可以识别文本文件:

YEAR1;PROJ1;
YEAR2;PROJ2;
YEAR3;PROJ3;

使用 ”;” 作为其分隔符。它确实在循环中运行,直到它完成的最后一个变量。但是,对于它的功能,我需要在文本文件中添加额外的行

YEAR4;PROJ4;
YEAR5;PROJ5;
end;

然后添加脚本

{ while IFS=';' read  YEAR1 PROJ1 YEAR2 PROJ2 YEAR3 PROJ3 YEAR4 PROJ4 YEAR5 PROJ5 fake
    do 
        { echo "$YEAR1" | egrep '^#|^ *$' ; } > /dev/null && continue 
            $local/script.sh \
                --forinput1 $YEAR1/$PROJ1  \
                --forinput2 $YEAR2/$PROJ2  \
                --forinput3 $YEAR3/$PROJ3  \
                --forinput4 $YEAR4/$PROJ4  \
                --forinput5 $YEAR5/$PROJ5  \
    done 
} < textFile.txt

我希望完成的是在数组中添加变量,但不必在脚本中添加额外的语法

这是坏的,但我猜我在看什么

{ while IFS=';' read -a YEAR PROJ < textFile.txt
for ((i = 0; i < "${#YEAR[@]};${#PROJ[@]}"; i++)); do
{ echo "$YEAR[$i]" | egrep '^#|^ *$' ; } > /dev/null && continue 
                $local/script.sh \
                    --forinput[$i] ${YEAR[$i]}/${PROJ[$i]}  \
        done 
    }

标签: arraysbashloopssh

解决方案


您的代码表明每个输入行有 6 个字段,这可能会导致代码如下

sed -nr 's#([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);#$local/script.sh --forinput \1/\2 --forinput \3/\4 --forinput \5/\6#p' textFile.txt
# or shorter
f='([^;]*;)'
sed -nr 's#'$f$f$f$f$f$f'#$local/script.sh --forinput \1/\2 --forinput \3/\4 --forinput \5/\6#p' textFile.txt

当你必须结合 3 行输入时,你不应该尝试变得聪明。

# Don't do this
cat textFile.txt | paste -d'X' - - - | tr -d 'X'
# Trying to make
sed -nr 's#'$f$f$f$f$f$f'#$local/script.sh --forinput \1/\2 --forinput \3/\4 --forinput \5/\6#p' <(cat textFile.txt | paste -d'X' - - - | tr -d 'X')

在自豪地展示代码之后,您会发现当第二行是注释(以“#”开头)时,您将不得不使代码变得更糟。您需要替换cat textFile.txtgrep -Ev '^#|^ *$' testFile.txt.

当您需要关联不同的行时,请查看awk.
没有检查的解决方案是

awk -F';' '{line++}
{param=param " --forinput " $1 "/" $2}
line==3 {print "$local/script.sh" param ; param=""; line=0}
' textFile.txt

您可以添加所有类型的检查。


推荐阅读