首页 > 解决方案 > 如何从一行中读取某些单词并将它们存储在 bash 脚本中的不同变量中?

问题描述

我想读取以下命令的输出并将该行中的某些单词存储到某些变量中:

ps -eaf |grep mongod

输出

root     12911     1  7 16:59 ?        00:05:48 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
root     22259  7895  0 18:16 pts/4    00:00:00 grep mongod

这里,“12911”是 PID,“/home/mongo/...”是 CMD。我想在这里写一个 if 条件(或者一个 for 循环?)来阅读

这是我到目前为止所拥有的:

ps -eaf | grep mongod | while read -r pid cmd; do
    echo "pid: $pid, cmd: $cmd"
done

电流输出:

pid: root, cmd: 12911     1  6 16:59 ?        00:05:56 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
pid: root, cmd: 24862 24860  0 18:29 pts/4    00:00:00 grep mongod

标签: linuxmongodbbashshell

解决方案


OP评论的假设和收集:

  • 可能有多个mongod进程(每个 OP 使用while循环)
  • 解析的数据需要存储在变量中以用于后续脚本(根据 OP 的评论)
  • OP 的ps命令允许格式化输出

由于ps输出在不同的 *nix 实现中可能会有很大差异,我将从ps输出我们需要的内容开始,例如:

ps -eo pid,cmd         # list all processes, only display the pid and command

然后我们可以通过管道将其传递给一个grep命令,以仅提取感兴趣的行(即包含mongod--port 27017

ps -eo pid,cmd | grep -- '[m]ongod .*--port 27017`

注意:放在m括号中应该消除命令的ps输出记录grep(即,不需要运行grep -v grep来跳过grep一行)

为了展示这个答案如何处理多个mongod进程,我正在使用两组ps输出(格式为-o pid,cmd):

12911 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
23952 /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-2 --oplogSize 700

为了允许解析的数据可用于后续处理,我们需要修改while循环结构以确保我们不会将解析的数据存储在子流程调用中。这表示:

# we replace this:

ps ... | grep ... | while read -r ...

# with this:

while read -r ... ; done < <(ps ... | grep ...)

将所有这些放在一起,我们有:

unset pids cmds dbpaths                  # make sure nothing in our array variables

i=1                                      # initialize our array index

while read -r pid cmd
do
    pids[i]="${pid}"                     # store current pid
    cmds[i]="${cmd}"                     # store current cmd

    dbpath="${cmd##*--dbpath[ =]}"
    dbpaths[i]="${dbpath%% *}"           # store current dbpath

    ((i++))                              # increment the array index for next pass through the loop
done < <(ps -eo pid,cmd | grep -- '[m]ongod .*--port 27017')

# at this point we've finished parsing the 'ps' output and follow-on
# processing can access this data via the 3x arrays, eg;

for (( i=1 ; i<=${#pids[@]} ; i++ ))
do
    echo "++++++++++++++++ dataset # ${i}"
    echo "pid:    ${pids[i]}"
    echo "cmd:    ${cmds[i]}"
    echo "dbpath: ${dbpaths[i]}"
done

echo "++++++++++++++++"

这会产生:

++++++++++++++++ dataset # 1
pid:    12911
cmd:    /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-1 --oplogSize 700
dbpath: /home/mongo/data/db/rs0-1
++++++++++++++++ dataset # 2
pid:    23952
cmd:    /home/mongo/bin/mongod -f /etc/mongod.conf --replSet mongoReplica --port 27017 --dbpath /home/mongo/data/db/rs0-2 --oplogSize 700
dbpath: /home/mongo/data/db/rs0-2
++++++++++++++++

推荐阅读