使用bash脚本从日志文件中提取唯一代码和uid

使用bash脚本从日志文件中提取唯一代码和uid,bash,awk,sed,grep,Bash,Awk,Sed,Grep,我不熟悉bash脚本,希望将日志文件中唯一的代码和uid提取到新的csv文件中,以便进一步处理 该文件包含: 2021-02-16T10:13:54.629Z,app,"Code: 01-87-04 & Diff [{:uid=>""asdf1234"", :sid=>636614}] / [{:uid=>""asdf1234"", :sid=>0}]" 2021-

我不熟悉bash脚本,希望将日志文件中唯一的代码和uid提取到新的csv文件中,以便进一步处理

该文件包含:

2021-02-16T10:13:54.629Z,app,"Code: 01-87-04 & Diff [{:uid=>""asdf1234"", :sid=>636614}] / [{:uid=>""asdf1234"", :sid=>0}]"
2021-02-16T10:11:22.914Z,app,"Code: 01-33-05 & Diff: [{:uid=>""kx4oa3hv"", :sid=>644448}, {:uid=>""v7jfxsum"", :sid=>643063}] / [{:uid=>""kx4oa3hv"", :sid=>0}, {:uid=>""v7jfxsum"", :sid=>0}]"
所需输出:

01-87-04, asdf1234
01-33-05, kx4oa3hv
01-33-05, v7jfxsum
我从这个脚本开始,阻止提取多个UID。感谢您的帮助

#!/bin/bash

echo "----->Loading file"
filename="some.csv"
while read -r line; do
  scene_id=`echo "$line" | awk '{print $2}'`

  echo $scene_id
done < "$filename"

使用以下Perl一行程序:

perl -lne '%seen = (); ( $code ) = /Code:\s+(\S+)/; @uids = grep { !$seen{$_}++ } /uid\W+(\w+)/g; print join ",", $code, $_ for @uids;' in_file > out_file
Perl one liner使用以下命令行标志: -e:告诉Perl在线查找代码,而不是在文件中。 -n:一次循环输入一行,默认情况下将其分配给$\并且默认情况下不打印它,而使用-p。 -l:在行内执行代码之前,默认情况下在*NIX上去掉\n输入行分隔符,并在打印时附加它

$code=/code:\s+\s+/;:提取代码。 @uids=grep{!$seen{${}++}/uid\W++\W++/g;:提取UID,使其独一无二。 打印连接,,$code,$\u@uids;:以csv格式打印代码和唯一uid,每行1个uid

另见:

在每个Unix设备上的任何shell中使用任何awk和排序:

$ awk -v OFS=', ' '{n=split($0,uids,/""/); for (i=2;i<n;i+=2) print $2, uids[i]}' file | sort -u
01-33-05, kx4oa3hv
01-33-05, v7jfxsum
01-87-04, asdf1234
对于sed:

或者,在普通bash中:


您应该将该脚本复制/粘贴到中,并修复它告诉您的内容。有关其他问题,请参阅。这只会在第二行数据上生成两个唯一uid值中的一个,其中代码为01-33-05。该行有4次出现uid,但只有2个唯一值。答案在其他方面非常好。@JonathanLeffler感谢您的评论和编辑。修正了错误,更新了答案。
sed '
    s/[^ ]* //
    s/ /, /
    :a
    /:uid=>""/!d
    s//\
/
    s/ .*\n/ /
    s/"",/\
/
    P
    s/ .*\n/ /
    ba' file | sort -u
#!/bin/bash

ldc='"Code: '  # left delimiter for code
rdc=' '        # right delimiter for code
ldu=':uid=>""' # left delimiter for uid
rdu='"",'      # right delimiter for uid

declare -A seen

while read -r line; do
    [[ $line = *"$ldc"*"$rdc"* ]] || continue
    code=${line#*"$ldc"}
    code=${code%%"$rdc"*}
    while [[ $line = *"$ldu"*"$rdu"* ]]; do
        line=${line#*"$ldu"}
        code_uid="$code, ${line%%"$rdu"*}"
        if [[ ! ${seen[$code_uid]} ]]; then
            seen[$code_uid]=1
            printf '%s\n' "$code_uid"
        fi
    done
done < file
01-87-04, asdf1234
01-33-05, kx4oa3hv
01-33-05, v7jfxsum