bash问题:2个变量而不是1个

时间:2014-03-28 16:02:09

标签: bash sed

我写了这段代码。

目标如下:

对于临时列表中的每个文件,它应该首先出现列表,将其放入名为$name1的变量中,然后将列表的第二次出现到名为$name2的第二个变量中。变量是文件名。使用2个变量,我做了一个连接。

for files in $(cat temp.lst); do
 if [ $(cat temp.lst | wc -l) == 1 ]
  then 
   name=$(head -1 temp.lst)
   join -t\; -j 1 file_minus1.txt "$name" | sed 's/;;/;/g' > file1.txt
  else
   name1=$(head -1 temp.lst)
   name2=$(head -2 temp.lst)
   echo "var1 "$name1 "var2 "$name2
   sed '1,2d' temp.lst > tmpfile.txt
   mv tmpfile.txt temp.lst
   join -t\; -j 1 "$name1" "$name2" | sed 's/;;/;/g' > file_minus1.txt
  fi
;done 

从理论上讲,它应该可行,但在这里它不起作用,唉。

我在代码中输入的echo行给了我3个变量而不是2个

var1 ei_etea17_m.tsv var2 ei_etea17_m.tsv ei_eteu25_m.tsv

更糟糕的是,加入并没有按照我想象的方式运行,而是给我这个错误代码

join: ei_etea17_m.tsv
ei_eteu25_m.tsv: No such file or directory

请查看我的temp.lst

的示例
ei_eteu27_m.tsv
ei_eteu28_m.tsv
ei_isbr_m.tsv
ei_isbu_m.tsv
ei_isin_m.tsv

欢迎任何建议。

最佳。

4 个答案:

答案 0 :(得分:3)

要在循环中提取文件的2行,请尝试以下操作:

paste - - < temp.lst | 
while read name1 name2; do
    if [[ -z $name2 ]]; then
        name2=$name1
        name1=file_minus1.txt
        output=file1.txt
    else
        output=file_minus1.txt
    fi
    join -t\; "$name1" "$name2" | sed 's/;;/;/g' > $output
done

注释

  • paste命令从文件中取出2行,并将它们连接成一行(由制表符分隔)
    • 演示:seq 7 | paste - -
  • read可以分配给多个变量:该行将在空格上拆分(默认)并分配给命名变量。
  • 在循环体中,我基本上遵循你的逻辑

答案 1 :(得分:1)

要执行n - 方式连接,请使用递归:)

recursive_join () {
    # Zero files: do nothing (special case)
    # One file: output it
    # Multiple files: join the first with the result of joining the rest
    file1=$1
    shift || return
    [ "$#" -eq 0 ] && cat "$file1" ||
      recursive_join "$@" | join -t\; -j1 "$file1" -
 }

 recursive_join ei_eteu27_m.tsv ei_eteu28_m.tsv ei_isbr_m.tsv ei_isbu_m.tsv ei_isin_m.tsv

对此进行调整以使用列出输入文件的文件,而不是使用命令行参数,这是一个小问题。只要没有输入文件名包含空格或其他特殊字符,您只需使用

即可
recursive_join $(cat temp.lst)

或者,如果您想利用bash功能,可以使用数组:

while read; do files+=("$REPLY"); done < temp.lst
recursive_join "${files[@]}"

bash 4:

readarray files < temp.list
recursive_join "${files[@]}"

但是,如果您只想坚持使用标准shell脚本,最好修改递归函数以从标准输入读取输入文件名。这使得函数变得更加丑陋,因为为了检测标准输入上是否只剩下一个文件,我们必须尝试读取第二个文件,如果成功则将其放回标准输入。

recursive_join () {
    IFS= read -r file1 || return
    IFS= read -r file2 &&
       { echo "$file2"; cat; } | recursive_join  | join -t\; -j1 "$file1" - ||
       cat "$file1"
}

recursive_join < temp.lst

创建一个可以使用 命令行参数或从标准输入读取列表的函数留给读者练习。

答案 2 :(得分:0)

变量name1获得第一行。 变量name2获得前两行。 如果你想让name2只有第二行你可以试试像:

name2=$(sed -n '2p')

同样sed -i将不再需要tmpfile.txt。

答案 3 :(得分:0)

Ok Gents或Ladies。

我发现了为什么。

head -1 temp.lst仅提供没有扩展名的文件名。

我需要找到一种方法来包含扩展名。可行的。