【问题标题】:how to write a bash for loop to create a template如何编写 bash for 循环来创建模板
【发布时间】:2021-07-10 05:33:15
【问题描述】:

如何编写 bash for 循环来创建模板

源文件:

    "INTEL SSDPEL1D380GA                   CCCCCCCCCCCCCCC    01",
    "Samsung SSD 970 PRO 1TB               XXXXXXXXXXXXXXX     01",
    "Samsung SSD 970 PRO 1TB               YYYYYYYYYYYYYYY     01",
    "Samsung SSD 970 PRO 1TB               ZZZZZZZZZZZZZZZ     01",
    "Samsung SSD 970 PRO 1TB               IIIIIIIIIIIIIII     01"

所需的输出:

node_nvme_device{manufacturer="INTEL",partnumber="SSDPEL1D380GA",serialnumber="CCCCCCCCCCCCCCC"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="XXXXXXXXXXXXXXX"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="YYYYYYYYYYYYYYY"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="ZZZZZZZZZZZZZZZ"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="IIIIIIIIIIIIIII"} 1

我尝试和失败的代码

awk 'NF>1 {
"node_nvme_device{manufacturer="$1",partnumber="$2",serialnumber="$3"} 1" }' source_file

【问题讨论】:

  • 请务必以代码的形式添加您的努力,这在 SO 上受到强烈鼓励,同时也避免对您的问题进行“近距离投票”/否决票(不是我的否决票),谢谢。跨度>
  • 编辑@RavinderSingh13

标签: bash for-loop awk sed scripting


【解决方案1】:

仅使用您展示的示例,请您尝试以下操作。

awk '
match($0,/".*               /){
  val1=""
  val=substr($0,RSTART+1,RLENGTH-1)
  sub(/[[:space:]]+$/,"",val)
  num=split(val,arr," ")
  for(i=2;i<=num;i++){
    val1=(val1?val1 OFS:"")arr[i]
  }
  printf("node_nvme_device{manufacturer=\"%s\",partnumber=\"%s\",serialnumber=\"%s\"} %01d\n",arr[1],val1,$(NF-1),$NF)
}' Input_file

说明: 只需使用awk 的匹配函数,按照所示样本从开始到直到更大的空间进行匹配,然后将其匹配的子字符串保存到 val 中,删除空格来摆脱它,然后创建 val2 ,它具有从第二个元素到数组末尾的 al 值(因为 OP 的样本中有多个值,例如 - > SSD 970 PRO 1TB 在此处匹配),然后最后打印这些值根据需要使用 printf 输出,只需传递值(当前行的字段和数组元素的字段,此处为 val1 值)。

【讨论】:

    【解决方案2】:

    可以使用单行,例如Perl 但使用 shell 脚本,您将拥有更多/更好的灵活性可扩展性可维护性以供以后使用用例。

    正确的解决方案将分为两个主要步骤:

    1. 先将文件读入数组
    2. 将每一行作为一个新数组读取

    所以对于 1 部分,您可以使用 mapfile 内置 bash 命令将您拥有的文件的所有行读入一个数组。

    #!/bin/bash
    mapfile -t arr < file.txt
    

    现在您将拥有每行的数组,例如echo ${arr[0]} 将打印您的第一行,echo ${arr[@]} 将打印所有行。然后您可以将每一行(步骤 2)读入另一个数组并使用它们:

    #!/bin/bash
    
    # read all lines
    mapfile -t arr < file.txt
    
    # read just line 1
    mapfile -t line1 < <(echo ${arr[0]} | tr ' ' '\n')
    
    # print first element of line 1
    echo ${line1[0]}
    
    # output
    "INTEL
    

    然后您可以将这两个步骤重构为您自己的特定步骤。


    请注意,您不必手动使用第二个mapfile(步骤2),您可以使用for-loop 来读取第一个数组(行数组),例如

    for line in ${arr[@]}; do
        # read each line into an new array
        mapfile -t each_line < <(echo ${line[@]} | tr ' ' '\n');
         
        # do whatever you need to do with each line
        echo "each line: ${each_line[@]}";
    done
    

    Plus 您应该删除文件中的多余字符,例如",等在使用内容/值之前。

    【讨论】:

    • 谢谢解释,我试试这个方法
    • mapfile -t arr &lt; file 不需要猫。
    【解决方案3】:

    这是另一个 awk 替代方案:

    awk '
    {
       mf = $1
       sn = $(NF-1)
       gsub(/^[[:blank:]]*"[^[:blank:]]+[[:blank:]]+|[[:blank:]]{2,}[[:alnum:]].*$/, "")
       printf "node_nvme_device{manufacturer=%s\",partnumber=\"%s\",serialnumber=\"%s\"} 1\n", mf, $0, sn
    }' file
    
    node_nvme_device{manufacturer="INTEL",partnumber="SSDPEL1D380GA",serialnumber="CCCCCCCCCCCCCCC"} 1
    node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="XXXXXXXXXXXXXXX"} 1
    node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="YYYYYYYYYYYYYYY"} 1
    node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="ZZZZZZZZZZZZZZZ"} 1
    node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="IIIIIIIIIIIIIII"} 1
    

    【讨论】:

      【解决方案4】:

      假设数据是制表符分隔并使用 Python:

      #!/usr/bin/python
      for f in open("parts"):                                # Open a file called parts
         f=f.replace("\"","")                                # Remove quotes from the line
         f=f.replace(",","")                                 # Remove commas from the line
         bits=f.split("\t")                                  # Split the line into the array bits based on tabs
         bits1=bits[0].split(" ")                            # Split the first index further into bits1 this time using " "
         stryng=bits1[0]
         numb=int(bits[2])
         for i in range(1,len(bits1),1):                     # Loop through bit1, building a strinf stryng
            stryng=stryng + " " + bits1[i]
         print("node_nvme_device{manufacturer=\"" + bits1[0] + "\",partnumber=\"" + stryng + "\",serialnumber=\"" + bits[1] + "\"} " + str(numb))       # Print the data in format required
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-05
        • 1970-01-01
        • 2014-09-03
        • 1970-01-01
        相关资源
        最近更新 更多