我有两个.txt文件,我想在.sh脚本中同时读取每行的行数.两个.txt文件都有相同的行数.在循环内部我想使用sed-command来更改另一个文件中的full_sample_name和sample_name.我知道如果你只是阅读一个文件,它是如何工作的,但我不能让它适用于两个文件.
#! /bin/bash
FULL_SAMPLE="file1.txt"
SAMPLE="file2.txt"
while read ... && ...
do
sed -e "s/\<full_sample_name\>/$FULL_SAMPLE/g" -e "s/\<sample_name\>/$SAMPLE/g" pipeline.sh > $SAMPLE.sh
done < ...?
Run Code Online (Sandbox Code Playgroud)
#!/bin/bash
full_sample_file="file1.txt"
sample_file="file2.txt"
while read -r -u 3 full_sample_name && read -r -u 4 sample_name; do
sed -e "s/\<full_sample_name\>/$full_sample_name/g" \
-e "s/\<sample_name\>/$sample_name/g" \
pipeline.sh >"$sample_name.sh"
done 3<"$full_sample_file" 4<"$sample_file" # automatically closed on loop exit
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我将文件描述符3分配给file1.txt,将文件描述符4分配给file2.txt.
顺便说一下,使用bash 4.1或更新版本,您不再需要手动处理文件描述符:
# opening explicitly, since even if opened on the loop, these need
# to be explicitly closed.
exec {full_sample_fd}<file1.txt
exec {sample_fd}<file2.txt
while read -r -u "$full_sample_fd" full_sample_name \
&& read -r -u "$sample_fd" sample_name; do
: do stuff here with "$full_sample_name" and "$sample_name"
done
# close the files explicitly
exec {full_sample_fd}>&- {sample_fd}>&-
Run Code Online (Sandbox Code Playgroud)
还有一点需要注意:如果您的输入文件不包含任何文字NUL [作为shell ,那么如果您的sample_name和full_sample_name值在被解释为正则表达式时无法保证自己评估,那么您可以使这更有效(并且更正确)脚本,它不应该],如果箭头括号是文字而不是字边界的正则表达式字符)完全不使用sed,只是读取输入要转换为shell变量,并在那里进行替换!
exec {full_sample_fd}<file1.txt
exec {sample_fd}<file2.txt
IFS= read -r -d '' input_file <pipeline.sh
while read -r -u "$full_sample_fd" full_sample_name \
&& read -r -u "$sample_fd" sample_name; do
output=${input_file//'<full_sample_name>'/${full_sample_name}}
output=${output//'<sample_name>'/${sample_name}}
printf '%s' "$output" >"${sample_name}.sh"
done
# close the files explicitly
exec {full_sample_fd}>&- {sample_fd}>&-
Run Code Online (Sandbox Code Playgroud)
查尔斯提供了一个很好的答案.
您可以使用paste一些分隔符(不应出现在文件中)来加入文件行:
paste -d ":" file1.txt file2.txt | while IFS=":" read -r full samp; do
do_stuff_with "$full" and "$samp"
done
Run Code Online (Sandbox Code Playgroud)