我是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