一个 for 循环可完成多项任务

一个 for 循环可完成多项任务

这段代码的输出是两个txt文件。我可以为他们两个做一个 for 循环吗?即一个 for 循环给我两个或多个输出?在 ID1 和 ID2 中我有文件名。我想打印 ID1 和 ID2 中每个条目的第一行并将其保存为 output1 和 output2 但我不想使用两个 for 循环。我正在寻找的是一个 for 循环来完成这项工作。

#!/bin/bash
in=/a/b/c
li=/a/b/c/d/
g1=/a/s/t1/1.txt
g2=/a/s/t2/2.txt

for i in $(cat $li/ID1.txt); do
    sed '1q;d' ${in}/${i}/${g1};
done > output1.txt

for i in $(cat $li/ID2.txt); do
    sed '1q;d' ${in}/${i}/${g2};
done > output2.txt

答案1

好吧,我想我现在明白变量中的路径名的作用了。

for n in 1 2; do n=$n.txt
for f in $(cat "$li/ID$n")
do IFS= read -r l <"$in/$f/a/s/t${n%.*}/$n"
    printf %s\\n "$l"
done > "output$n"; done

思考这就能实现你所追求的目标。如果是这样,它会使用 shell 内置函数来完成所有操作 - 也就是说,除了cat.

说到- 当像这里那样cat分割时,重要的是要明确 的值并避免在扩展中解释文件名全局。因为我不知道该文件的内容,所以我无法提供更多建议。$IFSfor ... in $(cmd sub)$IFSset -f

另一种方法可能涉及空字符串分隔符。这在很大程度上取决于$IFS分裂——它取决于扩张不是包括任何空字符串,因为它使用空字符串作为标记。如果您不更改$IFS并将其设置为默认值,则$(cat file)扩展将不包含任何空字符串。它可能是这样的:

io=/a/s/t1/1.txt
for f in $(cat "$li/ID1.txt") '' $(cat "$li/ID2.txt")
do [ -z "$f" ] && io=/a/s/t2/2.txt && continue
IFS= read -r l <"$in/$f/$io"
printf %s\\n "$l" >> "output${io##*/}"
done

或者你甚至可能会做...

n=0
for f in '' $(cat "$li/ID1.txt") '' $(cat "$li/ID2.txt")
do [ -z "$f" ] && exec >"output$((n+=1)).txt" && continue
IFS= read -r l <"$in/$f/a/s/t$n/$n.txt"
printf %s\\n "$l"
done

答案2

在这种特殊情况下,您根本不需要循环:

#!/usr/bin/env bash
in=/a/b/c
li=/a/b/c/d/
g1=/a/s/t1/1.txt
g2=/a/s/t2/2.txt

files1=$(sed "s#^#${in}/#;s#\$#/${g1}#" $li/ID1.txt | tr '\n' ' ')
files2=$(sed "s#^#${in}/#;s#\$#/${g2}#" $li/ID2.txt | tr '\n' ' ')

head -qn 1 $files1 > output1
head -qn 1 $files2 > output2

用于files1=...添加sed$in每行的开头和$g1结尾。这应该会产生目标文件名列表。然后您可以将所有的传递给sed打印第一行的。

重要的:这假设您的文件名是正常的(不包含空格、换行符或其他奇怪的字符)。如果情况并非如此,请告诉我,我会尽力提供更可靠的答案。请注意,您最初的for循环方法对于带有空格的文件名也会失败。


一般来说,无论您使用哪种语言,如果您发现自己编写重复的代码,您应该考虑使用函数:

#!/usr/bin/env bash

in=/a/b/c
li=/a/b/c/d/
g1=/a/s/t1/1.txt
g2=/a/s/t2/2.txt

firstline(){
    _in="$1"
    _g="$2"
    file="$3"
    while read i
    do
        sed '1q;d' ${in}/${i}/${g}
    done < "$file"
}

firstline "$li/ID1.txt" "$in" "$g1"  > output1.txt
firstline "$li/ID2.txt" "$in" "$g2"  > output2.txt

相关内容