修改awk脚本添加循环逻辑
Modify awk script to add looping logic
我有一个 awk 脚本来打印出现在我的文件名中的 pids。其中 myfilename 包含一个 pids 列表,每个出现在一个新行上...
ps -eaf | awk -f script.awk myfilename -
这里是 script.awk...
的内容
# process the first file on the command line (aka myfilename)
# this is the list of pids
ARGIND == 1 {
pids[[=11=]] = 1
}
# second and subsequent files ("-"/stdin in the example)
ARGIND > 1 {
# is column 2 of the ps -eaf output [i.e.] the pid in the list of desired
# pids? -- if so, print the entire line
if ( in pids)
printf("%s\n",[=11=])
}
目前 comman 按 ps -eaf 命令的顺序打印出 pids 但是我希望它按照它们在 myfilename 中出现的顺序打印出 pids。
我试图修改脚本以循环遍历 $pids 并重复相同的逻辑,但我不太正确。
如果有人能帮助我,我将不胜感激。
谢谢
原谅我生锈的 AWK。也许这是可用的?
ARGIND == 1 {
pids[[=10=]] = NR # capture the order
}
ARGIND > 1 {
if ( in pids) {
idx = pids[];
matches[idx] = [=10=]; # capture the line and associate it with the ps -eaf order
if (idx > max)
max = idx;
}
}
END {
for(i = 1; i <= max; i++)
if (i in matches)
print matches[i];
}
我不知道 ps -eaf
的输出是什么样的,也不知道从其输出中可以利用哪些假设。当我第一次阅读这个问题时,我认为 OP 对脚本有两个以上的输入。如果它真的只有两个,那么反转输入可能更有意义,如果不是,那么这可能是更通用的方法。
我会使用 time-honoured NR==FNR
构造来代替。它有点像这样 (one-liner)。
ps -eaf | awk 'NR==FNR{p[]++;next} in p' mypidlist -
NR==FNR
的想法是我们查看当前记录号(NR),并将其与当前文件(FNR)中的记录号进行比较。如果相同,则我们在同一个文件中,因此我们存储一条记录并移动到下一行输入。
如果 NR==FNR
不是 true,那么我们只需检查 </code> 是否在数组中。</p>
<p>所以第一个表达式用 <code>mypidlist
的内容填充数组 p[]
,第二个构造只是一个条件,默认为 {print}
作为它的语句。
当然,上面的one-liner并没有解决您要求按照pid输入文件的顺序打印结果的要求。为此,您需要保留一个索引并将数据记录在数组中以进行某种排序。当然不一定非得是real排序,只保留索引本身就足够了。下面有点长了一个one-liner:
ps -eaf | awk 'NR==FNR{p[]++;o[++n]=;next} in p {c[]=[=11=]} END {for(n=1;n<=length(o);n++){print n,o[n],c[o[n]]}}' mypidlist -
为了便于阅读,awk 脚本如下所示:
# Record the pid list...
NR==FNR {
p[]++ # Each pid is an element in this array.
o[++n]= # This array records the order of the pids.
next
}
# If the second+ input source has a matching pid...
in p {
c[]=[=12=] # record the line in a third array, pid as key.
}
END {
# At the end of our input, step through the ordered pid list...
for (n=1;n<=length(o);n++) {
print c[o[n]] # and print the collected line, using our pid index as key.
}
}
请注意,如果 ps
输出中缺少列表中的 pid,结果将打印一个空行,因为 awk 不会抱怨对不存在的数组索引的引用。
另请注意,length(arrayname)
表示法适用于 GAWK 和 OneTrueAwk,但可能不通用。如果这对你不起作用,你可以在你的 awk 脚本中添加这样的东西:
function alength(arrayname, i, n) {
for(i in arrayname)
n++
return n
}
如果只有一个文件,您可以翻转输入顺序并使用惯用的 awk
,如下所示
$ awk 'NR==1; NR==FNR{a[]=[=10=];next} [=10=] in a{print a[[=10=]]}' <(ps -eaf) <(seq 10)
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 02:36 ? 00:00:03 /sbin/init
root 2 0 0 02:36 ? 00:00:00 [kthreadd]
root 3 2 0 02:36 ? 00:00:00 [ksoftirqd/0]
root 4 2 0 02:36 ? 00:00:00 [kworker/0:0]
root 5 2 0 02:36 ? 00:00:00 [kworker/0:0H]
root 6 2 0 02:36 ? 00:00:00 [kworker/u30:0]
root 7 2 0 02:36 ? 00:00:00 [rcu_sched]
root 8 2 0 02:36 ? 00:00:00 [rcuos/0]
root 9 2 0 02:36 ? 00:00:00 [rcuos/1]
root 10 2 0 02:36 ? 00:00:00 [rcuos/2]
此处,seq
提供的 ID 列表,替换为您的文件。
我有一个 awk 脚本来打印出现在我的文件名中的 pids。其中 myfilename 包含一个 pids 列表,每个出现在一个新行上...
ps -eaf | awk -f script.awk myfilename -
这里是 script.awk...
的内容# process the first file on the command line (aka myfilename)
# this is the list of pids
ARGIND == 1 {
pids[[=11=]] = 1
}
# second and subsequent files ("-"/stdin in the example)
ARGIND > 1 {
# is column 2 of the ps -eaf output [i.e.] the pid in the list of desired
# pids? -- if so, print the entire line
if ( in pids)
printf("%s\n",[=11=])
}
目前 comman 按 ps -eaf 命令的顺序打印出 pids 但是我希望它按照它们在 myfilename 中出现的顺序打印出 pids。
我试图修改脚本以循环遍历 $pids 并重复相同的逻辑,但我不太正确。
如果有人能帮助我,我将不胜感激。
谢谢
原谅我生锈的 AWK。也许这是可用的?
ARGIND == 1 {
pids[[=10=]] = NR # capture the order
}
ARGIND > 1 {
if ( in pids) {
idx = pids[];
matches[idx] = [=10=]; # capture the line and associate it with the ps -eaf order
if (idx > max)
max = idx;
}
}
END {
for(i = 1; i <= max; i++)
if (i in matches)
print matches[i];
}
我不知道 ps -eaf
的输出是什么样的,也不知道从其输出中可以利用哪些假设。当我第一次阅读这个问题时,我认为 OP 对脚本有两个以上的输入。如果它真的只有两个,那么反转输入可能更有意义,如果不是,那么这可能是更通用的方法。
我会使用 time-honoured NR==FNR
构造来代替。它有点像这样 (one-liner)。
ps -eaf | awk 'NR==FNR{p[]++;next} in p' mypidlist -
NR==FNR
的想法是我们查看当前记录号(NR),并将其与当前文件(FNR)中的记录号进行比较。如果相同,则我们在同一个文件中,因此我们存储一条记录并移动到下一行输入。
如果 NR==FNR
不是 true,那么我们只需检查 </code> 是否在数组中。</p>
<p>所以第一个表达式用 <code>mypidlist
的内容填充数组 p[]
,第二个构造只是一个条件,默认为 {print}
作为它的语句。
当然,上面的one-liner并没有解决您要求按照pid输入文件的顺序打印结果的要求。为此,您需要保留一个索引并将数据记录在数组中以进行某种排序。当然不一定非得是real排序,只保留索引本身就足够了。下面有点长了一个one-liner:
ps -eaf | awk 'NR==FNR{p[]++;o[++n]=;next} in p {c[]=[=11=]} END {for(n=1;n<=length(o);n++){print n,o[n],c[o[n]]}}' mypidlist -
为了便于阅读,awk 脚本如下所示:
# Record the pid list...
NR==FNR {
p[]++ # Each pid is an element in this array.
o[++n]= # This array records the order of the pids.
next
}
# If the second+ input source has a matching pid...
in p {
c[]=[=12=] # record the line in a third array, pid as key.
}
END {
# At the end of our input, step through the ordered pid list...
for (n=1;n<=length(o);n++) {
print c[o[n]] # and print the collected line, using our pid index as key.
}
}
请注意,如果 ps
输出中缺少列表中的 pid,结果将打印一个空行,因为 awk 不会抱怨对不存在的数组索引的引用。
另请注意,length(arrayname)
表示法适用于 GAWK 和 OneTrueAwk,但可能不通用。如果这对你不起作用,你可以在你的 awk 脚本中添加这样的东西:
function alength(arrayname, i, n) {
for(i in arrayname)
n++
return n
}
如果只有一个文件,您可以翻转输入顺序并使用惯用的 awk
,如下所示
$ awk 'NR==1; NR==FNR{a[]=[=10=];next} [=10=] in a{print a[[=10=]]}' <(ps -eaf) <(seq 10)
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 02:36 ? 00:00:03 /sbin/init
root 2 0 0 02:36 ? 00:00:00 [kthreadd]
root 3 2 0 02:36 ? 00:00:00 [ksoftirqd/0]
root 4 2 0 02:36 ? 00:00:00 [kworker/0:0]
root 5 2 0 02:36 ? 00:00:00 [kworker/0:0H]
root 6 2 0 02:36 ? 00:00:00 [kworker/u30:0]
root 7 2 0 02:36 ? 00:00:00 [rcu_sched]
root 8 2 0 02:36 ? 00:00:00 [rcuos/0]
root 9 2 0 02:36 ? 00:00:00 [rcuos/1]
root 10 2 0 02:36 ? 00:00:00 [rcuos/2]
此处,seq
提供的 ID 列表,替换为您的文件。