我一直在努力学习剧本。我有一份体操队和比分列表。我设法得到文件管道分隔,就像下面的小数据示例。但是,现在我需要用空格替换管道,但只有在字母词之间。数字之间的管道必须保留。这样,我可以拥有团队名称,无论有多少单词构成,都可以作为一个领域。然后,数据就可以加载到我的数据库中了。我知道sed
或awk
使用正则表达式应该可以做到这一点,但我并不接近搞清楚。我整天搞砸了这一天,我相信有人可以在2分钟内告诉我如何做到这一点。 : - )
开始格式:
Twistars|28.250|28.700|28.100|27.950|113.600
Excel|Gymnastics|28.250|28.700|28.100|27.950|113.600
Head|Over|Heels|Gymnastics|28.250|28.700|28.100|27.950|113.600
我的最终目标:
Twistars|28.250|28.700|28.100|27.950|113.600
Excel Gymnastics|28.250|28.700|28.100|27.950|113.600
Head Over Heels Gymnastics|28.250|28.700|28.100|27.950|113.600
任何建议/小例子都会受到赞赏。
答案 0 :(得分:2)
以下是awk
解决方案:
awk -F\| '{printf $1;for (i=2;i<=NF;i++) printf (($(i-1)!~/[0-9.]+/ && $(i)!~/[0-9.]+/)?" ":"|")"%s",$i;print ""}' file
Twistars|28.250|28.700|28.100|27.950|113.600
Excel Gymnastics|28.250|28.700|28.100|27.950|113.600
Head Over Heels Gymnastics|28.250|28.700|28.100|27.950|113.600
答案 1 :(得分:2)
这可能适合你(GNU sed):
sed -r ':a;s/([[:alpha:]])\|([[:alpha:]])/\1 \2/g;ta' file
这将用空格替换单词之间的|
。第二次扫描捕获第一次传球中错过的任何比赛。
答案 2 :(得分:1)
sed 's/\([[:alpha:]]\)|\([[:alpha:]]\)/\1 \2/g' file
Twistars|28.250|28.700|28.100|27.950|113.600
Excel Gymnastics|28.250|28.700|28.100|27.950|113.600
Head Over Heels Gymnastics|28.250|28.700|28.100|27.950|113.600
答案 3 :(得分:1)
假设不应该加入最后5个字段:
awk '{p=$0; for(i=1;i<=NF-6;i++) sub(FS,OFS,p); print p}' FS='\\|' file
答案 4 :(得分:0)
echo 'Excel|Gymnastics|28.250|28.700|28.100|27.950|113.600' | sed 's/\([A-Za-z]\)\|\([A-Za-z]\)/\1 \2/g'
以上
的输出Excel Gymnastics|28.250|28.700|28.100|27.950|113.600
以上显示了您需要的基本sed
表达式。
你可以通过几种不同的方式进行修饰。
cat file | sed 's/\([A-Za-z]\)\|\([A-Za-z]\)/\1 \2/g' > newFile
sed 's/\([A-Za-z]\)\|\([A-Za-z]\)/\1 \2/g' file > newfile
您甚至可以使用某些版本的sed
使用“就地编辑”标记 - 这意味着您将把文件写回到同一个地方:
sed -i 's/\([A-Za-z]\)\|\([A-Za-z]\)/\1 \2/g' file
说明:
\([A-Za-z]\) capturing group: any character A-Z or a-z
\| escaped pipe symbol (otherwise it means "or")
\([A-Za-z]\) second capturing group: any character A-Z or a-z
我们用
替换上面的内容\1 \2 first captured group, space, second captured group
/g global flag: do it for all occurrences
答案 5 :(得分:0)
sed -e 's/\([[:alpha:]]\)|\([[:alpha:]]\)/\1 \2/g'
除了单个字母导致问题这一事实外,效果很好:
$ echo 'Tete|A|Tete|4.489' | sed -e 's/\([[:alpha:]]\)|\([[:alpha:]]\)/\1 \2/g'
Tete A|Tete|4.489
这可能使得awk成为更好的解决方案,尽管它更加冗长。
由于您已有文件,因此可以使用ex:
printf '%%s/\\([[:alpha:]]\\)|\\([[:alpha:]]\\)/\\1 \\2/g\n%%&g\n%%p\n' | ex -s file >file2
假设您正在使用支持here-documents的shell,您可以使其更具可读性,如下所示:
ex -s file >file2 <<EOF
%s/\([[:alpha:]]\)|\([[:alpha:]]\)/\1 \2/g
%&g
%p
EOF
它只是执行与sed一样的替换,除了它允许你使用&amp;重复它。命令。如果您希望它只是就地修改文件,请删除>file2
并将%p
更改为w
:
ex -s file <<EOF
%s/\([[:alpha:]]\)|\([[:alpha:]]\)/\1 \2/g
%&g
w
EOF
应该有&#34; sed for ex&#34;这使得ex的功能可用于管道输入,就像sed对ed一样,但我知道当前没有这样的实现。 Emacs附带一个手册,表明存在这样的实用程序,但该命令不可用,并且根据联机帮助页不会执行ex ..