从 bash 中的文件行获取字符串

get string from lines of file in bash

我在文件中有这些行:

postgres  2609 21030  0 12:49 ?        00:00:00 postgres: postgres postgres [local] idle in transaction                                                                     
postgres  2758 21030  0 12:51 ?        00:00:00 postgres: postgres postgres [local] idle in transaction                                                                     
postgres 28811 21030  0 09:26 ?        00:00:00 postgres: postgres postgres [local] idle in transaction                                                                     
postgres 32200 21030  0 11:40 ?        00:00:00 postgres: postgres postgres [local] idle in transaction                                                                     
postgres 32252 21030  0 11:41 ?        00:00:00 postgres: postgres postgres [local] idle in transaction                                                                     

我需要分隔第二列值来处理 them.I 已完成此代码:

pid=$(cat idle_log.txt | cut -d" " -f2)
echo $pid

但它只给了我 28811 32200 32252 在 results.as 你看列表中没有 2609 2758 的踪迹,我也想得到它们。 我还想在提取 pids 后对它们进行计数。 我用过:

npid=$(grep -o " " <<< $pid | grep -c .)

它 returns 2 对于 28811 32200 32252 的结果我需要它 return 3 作为进程数。 最后我想逐行处理一些事情,就像在 while 循环中一样,但是命令的输出 return 一次结果,我不能以循环格式逐个处理它们。

谢谢大家的帮助。

$ cat data 
postgres  2609 21030  0 12:49 ?        00:00:00 postgres: postgres postgres [local] idle in transaction
postgres  2758 21030  0 12:51 ?        00:00:00 postgres: postgres postgres [local] idle in transaction
postgres 28811 21030  0 09:26 ?        00:00:00 postgres: postgres postgres [local] idle in transaction
postgres 32200 21030  0 11:40 ?        00:00:00 postgres: postgres postgres [local] idle in transaction
postgres 32252 21030  0 11:41 ?        00:00:00 postgres: postgres postgres [local] idle in transaction   I need to extract second column from each line, 
$ awk '{print }' data 
2609
2758
28811
32200
32252

或者您可以使用 tr 将多个空格压缩为 1,然后像这样使用 cut

$ tr -s ' ' < data | cut -d ' ' -f 2
2609
2758
28811
32200
32252

编辑:

$ tr -s ' ' < data | cut -d ' ' -f 2 | while read -r line || [[ -n "$line" ]]; do
> echo "$line" #put your custom processing logic here
> done
2609
2758
28811
32200
32252

您可以使用tr压缩space然后使用cut取第二个space分隔字段:

tr -s ' ' <idle_log.txt | cut -d' ' -f2

awk:

awk '{ print  }' idle_log.txt

sed:

sed -r 's/^[^[:blank:]]+[[:blank:]]+([^[:blank:]]+)(.*)//' idle_log.txt

grep:

grep -Po '^[^\s]+\s+\K[^\s]+' idle_log.txt

为了use/count他们以后使用数组:

pids=( $(tr -s ' ' <idle_log.txt | cut -d' ' -f2) )

num_of_pids="${#pids[@]}"

$ printf '%s\n' "${pids[@]}" 
2609
2758
28811
32200
32252

示例:

$ tr -s ' ' <file.txt | cut -d' ' -f2 
2609
2758
28811
32200
32252

$ awk '{ print  }' file.txt        
2609
2758
28811
32200
32252

$ sed -r 's/^[^[:blank:]]+[[:blank:]]+([^[:blank:]]+)(.*)//' file.txt
2609
2758
28811
32200
32252

$ grep -Po '^[^\s]+\s+\K[^\s]+' file.txt
2609
2758
28811
32200
32252

cut 完全使用您传递给它的定界符。这意味着使用分隔符 ' ',第一行是:

postgres, <empty>, 2609

最后一个是:

postgres, 32252

你可以通过 运行 简化这个 awk '{print }' idle_log.txt

使用 Perl 正则表达式的 grep:

grep -oP '^[\S]+\s+\K[\S]+' file
2609
2758
28811
32200
32252

或者,

grep -o '^\([^[:blank:]]*[[:blank:]]*\)\{2\}' file |grep -o '[0-9]\+'
2609
2758
28811
32200
32252

我会选择最简单的解决方案:

pid=$(awk '{print }' idle_log.txt)
echo $pid

sed 和 grep 的正则表达式在脚本中的可读性要差得多,而 cut 和 tr 有时可能会产生意想不到的结果。

正如已经指出的那样,您没有得到结果的原因是您没有提取第二列。

相反,您使用的是命令 cut -d" " -f2,因此您得到了每行的第二个表空间分割。您可能会看到前两行有一个额外的表空间,因此您应该使用 cut -d" " -f3 但正如所讨论的,这不是获取第二列的正确方法。请改用 awk '{print }'