【问题标题】:bash command to create single ssh grep command using multiple values from a text file使用文本文件中的多个值创建单个 ssh grep 命令的 bash 命令
【发布时间】:2017-10-17 17:44:16
【问题描述】:

我在 RHEL6 下使用 bash shell, 我有一个包含三个条目的文本文件..

{text file}
lel
jts
sld

寻找最短的脚本/单行命令来生成单个 ssh 命令以减少我访问机器的次数

{end result}
ssh id@machine "grep -e lel -e jts -e sld {filename}"

【问题讨论】:

    标签: bash grep


    【解决方案1】:
    #!/bin/bash
    
    set -eu
    
    txtFile1="$1"
    txtFile2="$2"
    
    grepCmd="grep"
    
    for i in $(cat $txtFile1); do
      grepCmd="$grepCmd -e $i"
    done
    
    ssh id@machine "$grepCmd $txtFile2"
    

    执行如下:

    ./script "text file" "filename"
    

    【讨论】:

    • 这不会让我进入远程机器并使用本地机器上文件中的所有三个值执行 grep
    • 啊抱歉,我补充一下
    • 现在对你有用吗...还是你也必须提供 ssh 密码?
    • 复制 ssh 公钥使这些脚本更容易编写
    • --我已经有了可以去那里的好钥匙。 --我试图避免对文本文件中的每个条目进行 SSH。我想一次 ssh 并一次使用所有值 grep 但似乎无法通过 grep -e {value} -e {value} -e {值}
    【解决方案2】:
    ssh id@machine egrep '\|lel\|jts\|sld' {filename}
    

    ssh 命令行的参数必须被转义,因为 get 扩展了两次

    ssh id@machine egrep "$(readarray -t t<file1; printf "%s" "${t[0]}"; printf -- "\|%s" "${t[@]:1}")" file2
    

    其中 file1 是您的 {text file},而 file2 是远程机器上的另一个 {filename}

    【讨论】:

      【解决方案3】:

      如果远程机器有 Gnu grep(甚至可能有其他 grep),您可以使用 -f - 从标准输入一次读取一个正则表达式模式:

      ssh id@machine grep -f - {filename} < {patterns.txt}
      

      (请注意,&lt; {patterns.txt} 是您机器上 ssh 命令的重定向。不要引用它以将其作为命令的一部分传递。)

      ssh 构造用于远程执行的命令总是有点脆弱,因为ssh 实际上将命令(或在每个命令参数之间用单个空格字符连接的命令参数)作为单个字符串传递给用户在远程机器,使用-c 选项。这意味着您需要认真考虑如何引用参数,以防万一。当传递的参数来自其他地方时,这尤其令人讨厌,例如您的情况:如果文件的行包含空格或 shell 元字符,那么您需要安排适当地转义这些行,以便远程 shell 将正确解释它们。

      Bash 内置的printf 实用程序包含%q 格式代码,这对于构建此类命令行非常有用。例如,以下内容应该安全地引用文件中包含的模式:

      ssh id@machine "grep $(
        while IFS= read -r; do
          printf -- "-e %q " "$REPLY"
        done < {patterns.txt}) {filename}"
      

      或者,作为一个可能更具可读性的两行:

      mapfile -t patterns < {patterns.txt}
      ssh id@machine "grep $(printf -- "-e %q " "${patterns[@]}") {filename}"
      

      【讨论】:

        【解决方案4】:

        为了给您一些灵活性,您可以使用以下 awk 解决方案,只需生成命令并打印它:

        $ awk -v n="id@machine" -v f="filename" '\
        {a=((a)?a:"") " -e" $1}END{printf "ssh %s \"grep %s %s\"\n", n, a, f}' text
        ssh id@machine "grep  -elel -ejts -esld filename"
        

        但是,如果您对实际执行您的 ssh 并获取输出感兴趣,您将需要这样的东西:

        $ cat tst.awk
        {a=((a)?a:"") " -e" $1}                    # build up list of "-e ..."
        END{
           cmd="ssh " n " \"grep " a  " " f "\""   # concatenate cmd with vars "n" and "f"
           r=((cmd|getline line) > 0 ?line:"")     # execute cmd. check for errors.
           print r                                 # print result r
           close(cmd)                              # close the cmd
        }
        

        你可以这样称呼:

        awk -v n="id@machine" -v f="filename" -f tst.awk text
        

        或作为单行:

        $ awk -v n="id@machine" -v f="filename" '{a=((a)?a:"") " -e" $1}END{cmd="ssh " n " \"grep " a  " " f "\"";r=((cmd|getline line) > 0 ?line:"");print r;close(cmd)}' text
        

        您可以在 bash 脚本中使用它,循环多个机器和文件。你唯一需要做的就是用你的resp替换nf变量。 bash 变量。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-20
          相关资源
          最近更新 更多