想要改变字段分隔符以允许特定数据字段中的空格

时间:2014-07-21 21:30:50

标签: bash awk

我想破解一个bash脚本,该脚本在yad弹出窗口中输出用户的PID,并根据需要选择和kill PID。但是脚本使用awk格式化数据,我不熟悉awk。我会使用sed代替,但数据有11个字段,sed只允许9个缓冲区。

awk格式的问题是最后一个字段,$11是命令详细信息,它在描述中的第一个空格之后被切断,这是我不想要的。我想我可以在前10个之后替换所有空格,识别为字段分隔符,以防止命令描述细节在第一个空格后被删除。但这似乎有点hacky,我确信使用原始脚本中的awk命令可以有一种更明智的方式:

function gen_data() {

ps aux | tail -n +2 > "$TMPFILE" 
sed -ri "/$USER/!d" "$TMPFILE"
sed -ri "/$procName/!d" "$TMPFILE"
cat "$TMPFILE"

cat "$TMPFILE" | awk -F' ' '{print " " "\n" $1 "\n" $2 "\n" $3 "\n" $4 "\n" $5 "\n" $6 "\n" $7 "\n" $8 "\n" $9 "\n" $10 "\n" $11}' > "$OUTFILE" 
#`sed` edit
#cat "$TMPFILE" | sed -r 's/^([^ ]*)[ ]{1,}([^ ]*)[ ]{1,}([^ ]*)[ ]{1,}([^ ]*)[ ]{1,}[^ ]*[ ]{1,}[^ ]*[ ]{1,}([^ ]*)[ ]{1,}([^ ]*)[ ]{1,}([^ ]*)[ ]{1,}([^ ]*)[ ]{1,}(.*)$/\1\n\2\n\3\n\4\n\5\n\6\n\7\n\8\n\9/' > "$OUTFILE" 
cat "$OUTFILE"

}

我想知道是否有人介意帮忙解决这个问题?

更新
我设法通过使用while循环来更改$TMPFILE中的前十个空格,然后awk将其处理为制表符,从而保留了我想要的输出,这样可以保留PID描述中的所有空格机智:

function gen_data() {

    ps aux | tail -n +2 > "$TMPFILE" 
    sed -ri "/$USER/!d" "$TMPFILE"
    sed -ri "/$procName/!d" "$TMPFILE"
    cat "$TMPFILE"
    cntr=10
    while [[ "$cntr" -gt 0 ]] ; do
        sed -ri 's/[ ]{1,}/\t/' "$TMPFILE"
        ((cntr--))
    done

    cat "$TMPFILE" | awk -F '   ' '{print " " "\n" $1 "\n" $2 "\n" $3 "\n" $4 "\n" $5 "\n" $6 "\n" $7 "\n" $8 "\n" $9 "\n" $10 "\n" $11}' > "$OUTFILE"
}

我仍然会对任何替代/更好的方式感兴趣吗?

1 个答案:

答案 0 :(得分:2)

<强> EDITED

抱歉,我今天傻了!假设它从第70列开始,你可以使用substr()来获取命令:

awk '{command=substr($0,70); print command}' $TEMPFILE

另一个选项

您还可以获取与给定进程ID(pid)对应的命令,如下所示:

ps -p <PID> -xo command=

而不是删除所有不属于给定用户的行(就像你使用sed一样),你可能首先使用这样的命令更具体:

ps -u <uid> -xo pid=,uid=,command=

原始回答

我认为您可以使用FIELDWIDTHS变量告诉awk分割字段的位置,而不是使用空格。它是一个GNU扩展,我不知道ps aux命令中字段的宽度,所以你必须计算它们: - )

awk 'BEGIN{FIELDWIDTHS="14 8 6 6 6 8 6 8 6 8 200"}{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11}' $TMPFILE

只需使最后一个字段的宽度很大,即可捕获所有命令。