用于数据清理的Bash shell



我是bash脚本的新手,我正在学习数据清理脚本。我有一个大文件,我已经设法剪掉必要的列,并将其保存到一个新文件。需要帮助来实现我正在寻找的结果。

2 Media Server Community - WebRTC, MP4, HLS, RTMP"
29 Media Server Enterprise
7 Media Server lite
10 Media server lite 1.0
468 Media server lite 2.0
8 Media server lite 2.3
1 Media server lite 2.4
40 Media server lite 3.0
3 Media server lite 3.3

我如何编辑这个文件,现在使csv文件为

2 | Media Server Community - WebRTC, MP4, HLS, RTMP"
29 | Media Server Enterprise
7 | Media Server lite
10 | Media server lite 1.0
468 | Media server lite 2.0
8 | Media server lite 2.3
1 | Media server lite 2.4
40 | Media server lite 3.0
3 | Media server lite 3.3

我宁愿看到您发布(部分)原始数据文件,并向您展示如何使用awk完成所有操作,但以下是您要求使用GNU awk (gensub)的内容:

$ gawk '{print gensub(/([0-9]+ )/,"\1| ",1,$0)}' file

输出:

2 | Media Server Community - WebRTC, MP4, HLS, RTMP"
29 | Media Server Enterprise
7 | Media Server lite
...

编辑:嗯,我猜最近gensub太多了,就用awk:

$ awk '{sub(/([0-9]+ )/,"&| ")}1' file

任何awk的另一种方法是使用match()定位第一个数字和空白结束的地方,然后使用substr()打印到该点,添加"|",然后再次使用substr()从该点打印到结束,例如

awk '{ 
match($0,/^[ t0-9]+/)
print substr($0,0,RLENGTH-1), "|", substr($0, RLENGTH+1)
}'

使用/输出示例

对于文件名为media的示例输入,您可以这样做:
$ awk '{ match($0,/^[ t0-9]+/); print substr($0,0,RLENGTH-1), "|", substr($0, RLENGTH+1) }' media
2 | Media Server Community - WebRTC, MP4, HLS, RTMP"
29 | Media Server Enterprise
7 | Media Server lite
10 | Media server lite 1.0
468 | Media server lite 2.0
8 | Media server lite 2.3
1 | Media server lite 2.4
40 | Media server lite 3.0

所有bash/zsh的答案

如果你不喜欢第一个字段周围的空白,你可以这样做:

$ while read -r x rest; do printf "%s|%sn" "$x" "$rest"; done <file
2|Media Server Community - WebRTC, MP4, HLS, RTMP"
29|Media Server Enterprise
7|Media Server lite
10|Media server lite 1.0
468|Media server lite 2.0
8|Media server lite 2.3
1|Media server lite 2.4
40|Media server lite 3.0
3|Media server lite 3.3

结果是一个单字符"|"分隔符CSV文件,而不是具有三个字符" | "的CSV分隔符(后面更难处理…)

如果您希望第一个字段更宽,并且是一个列,您可以使用Bash正则表达式将第一个字段与其他字段分开:

while IFS= read -r line || [[ -n $line ]]; do 
if [[ $line =~ ^[[:blank:]]*([[:digit:]]+)[[:blank:]]+(.*) ]]; then
printf "%4s | %sn" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
fi  
done <file 
2 | Media Server Community - WebRTC, MP4, HLS, RTMP"
29 | Media Server Enterprise
7 | Media Server lite
10 | Media server lite 1.0
468 | Media server lite 2.0
8 | Media server lite 2.3
1 | Media server lite 2.4
40 | Media server lite 3.0
3 | Media server lite 3.3

对于一个简单的答案,我会这样做:

awk -v de=" | " '
FNR==NR{length($1)>max ? max=length($1) : max=max; next}
{
s=""
for (i=2;i<=NF;i++) s=s ? s OFS $i : $i
printf " %*s%s%sn", max, $1, de, s
}
' file file
2 | Media Server Community - WebRTC, MP4, HLS, RTMP"
29 | Media Server Enterprise
7 | Media Server lite
10 | Media server lite 1.0
468 | Media server lite 2.0
8 | Media server lite 2.3
1 | Media server lite 2.4
40 | Media server lite 3.0
3 | Media server lite 3.3

Withsed(1)

sed 's/^([[:space:]]*[[:digit:]]{1,})/1 |/' file.txt 

  • ^是一个锚,意思是开始/开始。

  • ( )是一个捕获组,(()需要用B.R.E.转义)里面的任何模式都将在1中出现。这是第一个捕获组

  • [[:space:]]留白。

  • *是一个量词,表示零或更多。

  • [[:digit:]]为整型。

  • {1,}是一个量词,表示一个或多个,但{}需要用B.R.E.进行转义,这是sed默认的正则表达式引擎。


如果使用-E标志/选项(E.R.E.),可以在模式匹配中省略转义。

sed -E 's/^([[:space:]]*[[:digit:]]{1,})/1 |/' file.txt

相关内容

  • 没有找到相关文章

最新更新