如何编写 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 部分,您可以使用 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
如何编写 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 部分,您可以使用 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