【问题标题】:get the first 5 characters from each line in shell script获取 shell 脚本中每一行的前 5 个字符
【发布时间】:2023-03-07 15:36:01
【问题描述】:

这是我的 sample.txt 文件,其中包含以下内容

31113    70:54:D2 - a-31003
31114    70:54:D2 - b-31304
31111    4C:72:B9 - c-31303
31112    4C:72:B9 - d-31302

我必须编写 shell 脚本,因为我将前 5 个字符(例如 31113)作为输入 id 传递给其他脚本。为此我已经尝试过这个

#!/bin/sh
filename='sample.txt'
filelines=`cat $filename`
while read -r line
do
  id= cut -c-5 $line
  echo $id
  #code for passing id to other script file as parameter
done < "$filename"

但它不起作用,这给了我错误

cut: 31113: No such file or directory
cut: 70:54:D2 No such file or directory
31114
31111
31112
: No such file or directory

我该怎么做?

【问题讨论】:

    标签: linux bash shell sh cut


    【解决方案1】:

    sed 与匹配前 5 个字符并仅返回该组的捕获组一起使用:

    sed -E 's/(.{0,5}).*/\1/' sample.txt
    

    (.{0,5}) 贪婪匹配任意字符最多 5 次,并创建一个捕获组。

    .* 匹配行的其余部分,因为我们要替换整行,而不仅仅是捕获组。

    \1 是指向第一个捕获组的反向引用。

    所以我们正在捕获我们想要的 5 个字符的组,然后仅用该捕获组替换整个匹配的行。

    【讨论】:

      【解决方案2】:

      如果你想这样使用cut,你需要使用redirection &lt;&lt;&lt;(这里的字符串),比如:

      var=$(cut -c-5 <<< "$line")
      

      注意使用var=$(command) 表达式而不是id= cut -c-5 $line。这是将命令保存到变量中的方法。

      另外,使用/bin/bash 而不是/bin/sh 让它工作。


      对我有用的完整代码:

      #!/bin/bash
      
      filename='sample.txt'
      while read -r line
      do
        id=$(cut -c-5 <<< "$line")
        echo $id
        #code for passing id to other script file as parameter
      done < "$filename"
      

      【讨论】:

      • 它确实有效,但这不是写这个的惯用方式!
      • 小语义说明,通常称为“重定向”而不是“间接”。 (“间接”通常用于表示“通过代码的非线性路径”)
      • 更容易理解:cut -c -5 只打印前 5 个字符。这更好读:cut -c 1-5
      【解决方案3】:

      请检查以下简单示例:

      while read line; do id=$(echo $line | head -c5); echo $id; done < file
      

      head -c5 是从字符串中获取前 5 个字符的正确命令。

      【讨论】:

        【解决方案4】:

        比上面的答案简单一些:

        #!/bin/bash
        filename='sample.txt'
        while read -r line; do
          id=${line:0:5}
          echo $id
          #code for passing id to other script file as parameter
        done < "$filename"
        

        【讨论】:

          【解决方案5】:

          如果您尝试从文件中获取第一列,请尝试awk

          #!/bin/sh
          filename='sample.txt'
          
          while read -r line
          do
            id=$(echo $line | awk '{print $1}')
            echo $id
            #code for passing id to other script file as parameter
          done < "$filename"
          

          【讨论】:

          • 这究竟是如何打印 sample.txt 每一行的前 5 个字符的?
          • @RedX awk 分隔每一行(默认为space)并打印第一个字段('{print $1}'),即前5个字符。
          【解决方案6】:

          而不是将echo 传递到cut,只需将cut 的输出直接传递到while 循环:

          cut -c 1-5 sample.txt |
          while read -r id; do
            echo $id
            #code for passing id to other script file as parameter
          done
          

          【讨论】:

          • 为什么需要while循环?
          • 如果唯一的命令是echo,那么while循环是完全没有必要的,但我认为在由占位符持有的真实脚本中会发生更多事情:#code for passing id to other script file as parameter
          【解决方案7】:

          嗯,它是单行的cut -c-5 sample.txt。示例:

          $ cut -c-5 sample.txt 
          31113
          31114
          31111
          31112
          

          从那里开始,您可以将其通过管道传输到任何其他脚本或命令:

          $ cut -c-5 sample.txt | while read line; do echo Hello $line; done
          Hello 31113
          Hello 31114
          Hello 31111
          Hello 31112
          

          【讨论】:

            【解决方案8】:

            也许你需要这个,awk 可以自动识别空白。

            awk '{print $1}' sample.txt
            

            【讨论】:

            • 这究竟是如何打印 sample.txt 每一行的前 5 个字符的?
            • 你看,vanda用类似的方式回答问题,这对你来说有意义吗?有时,请求者不知道如何正确表达他们的请求。
            • 嘿嘿,你真专注,Rep什么都不是。
            • +1:在问题中指定的情况下,前5个字符也是空格分隔文本的第一个字段,所以这个答案是一个完全合理的方法。
            • @WilliamPursell 是的,vanda 解释了它。也谢谢你的解释。
            猜你喜欢
            • 1970-01-01
            • 2013-08-04
            • 2012-02-02
            • 2017-10-03
            • 1970-01-01
            • 2015-05-14
            • 2021-08-03
            • 2013-02-04
            相关资源
            最近更新 更多