我想从一个字符串中获取变量 $color 和 $number,通常是这样的:“something, numColor (number)”。颜色可能是 W、U、B、R、G。如果没有颜色,如果逗号之前的字符串没有单词 land 或 L,则变量颜色应该是 C。如果有不止一种颜色,变量 $color 应该是 M。以下是字符串可能的样子以及变量应该是什么的一些示例:
- 魔法,R (1)
$color=R, $number=1
- 生物~兽 5/3、4G (5)
$color=G $number=5
- 巫术,1WWU (4)
$color=M $number=4
- 传奇之地
$color=L $number=0
- 神器, 0
$color=C $number=0
- 传奇生物~奥札奇 15/15, 15 (15)
$color=C $number=15
答案1
您可以通过sed
在线完成任务:
sed '/(\?\([0-9]\+\))\?$/s//; number=\1/
t n
s/$/; number=0/
:n
/^.*, [0-9]\?\([WURBG]\)/{
s//color=\1/
s/[WURBG]\{2,\}/M/
}
/[Ll]and/s/^[^;]*/color=L /
/color/!s/^[^;]*/color=C /' file
但我想提供 put 命令script file
:
#!/bin/sed -f
/(\?\([0-9]\+\))\?$/s//; number=\1/
t n
s/$/; number=0/
:n
/^.*, [0-9]\?\([WURBG]\)/{
s//color=\1/
s/[WURBG]\{2,\}/M/
}
/[Ll]and/s/^[^;]*/color=L /
/color/!s/^[^;]*/color=C /
然后做
sed -f script.file file
请注意,上述所有正则表达式仅在您的示例中进行了测试,如果您遇到不正确的工作,可以通过一点调整来解决。
答案2
grep
虽然您可以通过将更原始的 Unix 工具( 、sed
、等)包装在 shell 脚本中来完成这类事情awk
,但这类问题确实需要用具有强大正则表达式系统的完整编程语言来处理。就我个人而言,我会选择 Perl:
#!/usr/bin/perl -w
use strict;
my $line = 0;
my ($junk, $color, $number);
open my $data, '<', 'data.txt' or die "open: $!\n";
while (<$data>) {
chomp;
++$line;
if (m/Land/) {
print "color=L, number=0\n";
}
else {
($junk, $color, $number) = m/, (\d+)?([WURBG]+) \((\d+)\)$/;
if (defined $color and defined $number) {
$color = 'M' if length($color) > 1;
print "color=$color, number=$number\n";
}
else {
($junk, $number) = m/, (\d+)? ?\((\d+)\)$/;
if (defined $number) {
print "color=C, number=$number\n";
}
else {
print "Line #$line is malformed!\n";
}
}
}
}
data.txt
包含这个:
Sorcery, R (1)
Creature — Beast 5/3, 4G (5)
Sorcery, 1WWU (4)
Legendary Land
Artifact, (0)
Legendary Creature — Eldrazi 15/15, 15 (15)
与您发布的内容只有一个区别:问题中的“Artifact”行在 0 值周围没有括号,这需要在解析器中进行例外处理。可以添加它,但我不明白为什么这比修复数据文件的格式更好。
我假设您不只是想要像此脚本那样打印出颜色和数值。您可以为每一print
行添加您自己的代码。
该$junk
位来自我的假设,即颜色字母之前的数字可能很重要。我用它来帮助解析器完成它的任务。如果您确实需要该数字,则可以重命名该$junk
变量以使其具有语义含义。这对我来说只是“垃圾”,因为我不知道其价值意味着什么。