Bash命令根据我传递的参数读取一行-执行基于列的查找

Bash命令根据我传递的参数读取一行-执行基于列的查找,bash,unix,awk,sed,lookup,Bash,Unix,Awk,Sed,Lookup,我有一个links.txt文件: 1 a.sh 3 b.sh 6 c.sh 4 d.sh 因此,如果我将1,4作为参数传递给另一个文件(master.sh),a.sh和d.sh应该存储在一个变量中 循环遍历每个参数,并在链接文件中对其进行greps。结果通过管道传输到cut中,在这里我们将分隔符指定为带-d标志的空格,将字段号指定为带-f标志的2。最后,它被附加到名为files的数组中 links="links.txt" files=() for arg in $@; do file

我有一个links.txt文件:

1 a.sh
3 b.sh
6 c.sh
4 d.sh

因此,如果我将1,4作为参数传递给另一个文件(master.sh),a.sh和d.sh应该存储在一个变量中

循环遍历每个参数,并在链接文件中对其进行greps。结果通过管道传输到cut中,在这里我们将分隔符指定为带-d标志的空格,将字段号指定为带-f标志的2。最后,它被附加到名为files的数组中

links="links.txt"
files=()

for arg in $@; do
    files=("${files[@]}" `grep "^$arg" "$links" | cut -d" " -f2`)
done;

echo ${files[@]}
用法:

$ ./master.sh 1 4
a.sh d.sh
$ ./master.sh 1 4
a.sh d.sh
编辑: 正如mklement0所指出的,上面的解决方案每个参数读取一次文件。下面的代码首先构建模式,然后只读取文件一次

links="links.txt"
pattern="^$1\s"
for arg in ${@:2}; do
    pattern+="|^$arg\s"
done
files=$(grep -E "$pattern" "$links" | cut -d" " -f2)
echo ${files[@]}
用法:

$ ./master.sh 1 4
a.sh d.sh
$ ./master.sh 1 4
a.sh d.sh

这将循环遍历每个参数,并在链接文件中对其进行greps。结果通过管道传输到cut中,在这里我们将分隔符指定为带-d标志的空格,将字段号指定为带-f标志的2。最后,它被附加到名为files的数组中

links="links.txt"
files=()

for arg in $@; do
    files=("${files[@]}" `grep "^$arg" "$links" | cut -d" " -f2`)
done;

echo ${files[@]}
用法:

$ ./master.sh 1 4
a.sh d.sh
$ ./master.sh 1 4
a.sh d.sh
编辑: 正如mklement0所指出的,上面的解决方案每个参数读取一次文件。下面的代码首先构建模式,然后只读取文件一次

links="links.txt"
pattern="^$1\s"
for arg in ${@:2}; do
    pattern+="|^$arg\s"
done
files=$(grep -E "$pattern" "$links" | cut -d" " -f2)
echo ${files[@]}
用法:

$ ./master.sh 1 4
a.sh d.sh
$ ./master.sh 1 4
a.sh d.sh

sed'3!d'
将打印第三行,但不会打印以
3开头的行。为此,您需要
sed'/^3/!d'
。问题是你不能将它们组合成更多的行,因为这意味着“删除所有不以3开头的行”,这意味着所有其他行都将丢失。因此,请改用
sed-n'/^3/p'
,即默认情况下不打印,并告诉sed要打印哪些行,而不是要删除哪些行

您可以在参数上循环并从中创建一个sed脚本,用于打印行,然后使用以下输出运行
sed

#!/bin/bash
file=$1
shift

for id in "$@" ; do
    echo "/^$id /p"
done | sed -nf- "$file"
script.sh文件名3 4
运行

如果要从输出中删除id,可以使用

cut -f2 -d' '
或者,您可以修改生成的sed脚本来完成这项工作

echo "/^$id /s/.* //p"

i、 e.仅当替换成功时才打印。

sed'3!d'
将打印第三行,但不会打印以
3开头的行。为此,您需要
sed'/^3/!d'
。问题是你不能将它们组合成更多的行,因为这意味着“删除所有不以3开头的行”,这意味着所有其他行都将丢失。因此,请改用
sed-n'/^3/p'
,即默认情况下不打印,并告诉sed要打印哪些行,而不是要删除哪些行

您可以在参数上循环并从中创建一个sed脚本,用于打印行,然后使用以下输出运行
sed

#!/bin/bash
file=$1
shift

for id in "$@" ; do
    echo "/^$id /p"
done | sed -nf- "$file"
script.sh文件名3 4
运行

如果要从输出中删除id,可以使用

cut -f2 -d' '
或者,您可以修改生成的sed脚本来完成这项工作

echo "/^$id /s/.* //p"

i、 e.仅在替换成功时打印。

以下
awk
解决方案

  • 保留参数顺序;也就是说,结果反映了指定查找值的顺序(与查找值在文件中出现的顺序相反)

    • 如果这并不重要(即,如果可以接受按文件顺序输出结果),则可以将下面的
      readarray
      技术与这一行程序结合使用,这是:

      grep-f以下
      awk
      解决方案

      • 保留参数顺序;也就是说,结果反映了指定查找值的顺序(与查找值在文件中出现的顺序相反)

        • 如果这并不重要(即,如果可以接受按文件顺序输出结果),则可以将下面的
          readarray
          技术与这一行程序结合使用,这是:

          grep-f这里是grep和cut的另一个示例:

          #!/bin/bash
          for line in $(grep "$1\|$2" links.txt|cut -d' ' -f2)
          do
              echo $line
          done
          
          用法示例:

          ./master.sh 1 4
          a.sh
          d.sh
          

          下面是grep和cut的另一个示例:

          #!/bin/bash
          for line in $(grep "$1\|$2" links.txt|cut -d' ' -f2)
          do
              echo $line
          done
          
          用法示例:

          ./master.sh 1 4
          a.sh
          d.sh
          

          为什么不存储这些值并随意调用它们:

          items=()
          
          while read -r num file
          do
            items[num]="$file"
          done<links.txt
          
          for arg
          do
            echo "${items[arg]}"
          done
          
          items=()
          读取-r num文件时
          做
          items[num]=“$file”
          
          完成为什么不存储值并随意调用它们:

          items=()
          
          while read -r num file
          do
            items[num]="$file"
          done<links.txt
          
          for arg
          do
            echo "${items[arg]}"
          done
          
          items=()
          读取-r num文件时
          做
          items[num]=“$file”
          
          完成您尝试了什么?请发布您的第一次尝试。LB是换行
          cat文件|,同时读取line
          LB
          do
          。它遍历文件的所有行,但我希望根据参数读取该行。
          sed'3!d'links.txt
          这给了我文件的第三行注意,这个问题没有指定结果是否必须反映参数顺序,或者是否可以按照文件中出现查找数字的顺序返回结果。例如,参数列表
          61
          必须导致
          c.sh
          a.sh
          (按该顺序),或者返回
          a.sh
          c.sh
          之前是否可以,因为ID
          1
          恰好位于文件中
          6
          之前?我对现有答案进行了标记,以澄清它们实施的两种解决方案中的哪一种。您尝试了什么?请发布您第一次尝试的内容。LB是换行
          cat file;,同时读取line
          LB
          do
          。它遍历文件的所有行,但我希望根据参数读取该行。
          sed'3!d'links.txt
          这给了我文件的第三行注意,这个问题没有指定结果是否必须反映参数顺序,或者是否可以按照文件中出现查找数字的顺序返回结果。例如,参数列表
          61
          必须导致
          c.sh
          a.sh
          (按该顺序),或者返回
          a.sh
          c.sh
          之前是否可以,因为ID
          1
          恰好位于文件中
          6
          之前?我已经标记了现有的答案,以澄清他们实施的两个解决方案中的哪一个。嗨,谢谢@choroba。当我通过3 4时,其显示
          3 b.sh
          4