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

how to write a bash for loop to create a template

如何编写 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="",partnumber="",serialnumber=""} 1" }' source_file

可以使用单线,例如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 你应该删除文件中的额外字符,例如" , ,, 等等 在使用内容/值之前。

只有你展示的样品,请你试试看。

awk '
match([=10=],/".*               /){
  val1=""
  val=substr([=10=],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的匹配函数来匹配从开始到更大的space作为每个显示的样本,然后将其匹配的子字符串保存到 val 中,删除 spaces 以摆脱它,然后创建 val2,它具有从第二个元素到数组末尾的 al 值(因为样本中有多个值通过 OP eg--> SSD 970 PRO 1TB 以匹配此处),然后最终使用 printf 根据需要输出打印值,只需传递值(当前行的字段和数组元素的 val1 值)。

假设数据以制表符分隔并使用 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

这是另一个 awk 替代方案:

awk '
{
   mf = 
   sn = $(NF-1)
   gsub(/^[[:blank:]]*"[^[:blank:]]+[[:blank:]]+|[[:blank:]]{2,}[[:alnum:]].*$/, "")
   printf "node_nvme_device{manufacturer=%s\",partnumber=\"%s\",serialnumber=\"%s\"} 1\n", mf, [=10=], 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