#c# #regex
#c# #регулярное выражение
Вопрос:
Из .*tan(.*tan(.*)).*
и только .*tan(.*tan(.*)).*
, я хочу сопоставить внутреннюю tan(.*)
.
Регулярное выражение
tan([0-9a-zA-Z. -*/()![tan]] )
Пример
От:
tan(80.1*tan(81.7 (80.9 81.5))) 81.9
Я хочу извлечь внутреннюю:
tan(81.7 (80.9 81.5))
Но не:
tan(80.1*tan(81.7 (80.9 81.5)))
Ответ №1:
Вы можете использовать три регулярных выражения. (Я знаю! Безумие, не так ли?)
Первое извлечение:
^tan(.*?tan(.*?).*?)$
Затем извлеките:
^(?=(tan(.*?))tan(.*?).*$
Затем извлеките:
^tan(.*?)(?=(.*?).*?))$
Если вы используете Perl, это намного проще:
$mystr =~ s^.*?tan(.*?(tan(.*?)).*?).*$1;
Редактировать:
Я не знаю точно, чего вы хотите, но, судя по вашему комментарию к сообщению @Thorbear, я не думаю, что вам следует использовать регулярные выражения. Вы не можете анализировать контекстно-свободные грамматики только с помощью регулярных выражений [C #].
Что вам нужно, так это анализатор выражений, а не регулярное выражение.
Комментарии:
1. это не только два tan, если их много tan, сначала ожидайте получить самый внутренний tan (XXX), почему бы не исключить tan?
Ответ №2:
static void Main(string[] args){
var str = "tan(80.1*tan(81.7 (80.9 81.5))) 81.9";
Console.WriteLine(innerTan(str));
}
static string innerTan(string str){
const string token = "tan(";
if(!str.Contains(token))
return String.Empty;
var spos = str.IndexOf(token);
var epos = spos token.Length;
var balance = 1;
for(var i = epos ;i < str.Length; i){
switch (str[i]){
case '(':
balance;break;
case ')':
--balance;break;
}
if(balance == 0){
epos = i;
break;
}
}
var innerText = str.Substring(spos token.Length, epos - spos);
if(innerText.Contains(token))
return innerTan(innerText);
else
return str.Substring(spos, epos - spos 1);
}
Комментарии:
1. C # (.NET) Я, вероятно, не стал бы считать, что скобки регулярного выражения сбалансированы.
2. Возможно, невозможно. В регулярных выражениях я не могу сопоставить количество скобок, которые помещаются в левую и правую круглые скобки. (Возможно, Perl может сделать)
Ответ №3:
Немного не уверен в ваших требованиях… но что-то вроде tan(.*?(tan(.*)))
сохранит внутренний tan() в $1
Для ваших групп символов вам не нужно экранировать символы [0-9a-zA-Z. */-]
, будет достаточно, просто будьте осторожны с тем, где вы размещаете -
Редактировать:
если у вас есть неизвестное количество tan() внутри друг друга, вам понадобится что-то вроде tan((.(?!tan))*?)
захвата самого внутреннего. Однако впоследствии вам придется сбалансировать круглые скобки, так как subject like tan(80.1*tan(81.7 (80.9 81.5)))
вернет совпадение tan(81.7 (80.9 81.5)
. Кроме того, если ваш объект выглядит так tan(80.1*tan(81.7 (80.9 81.5) (80.9 81.5)))
, что шаблон не будет захватывать последнее (80.9 81.5)
, удаление последнего ?
решит эту проблему, но тогда у вас возникнут проблемы с такими объектами, как tan(80.1*tan(81.7 (80.9 81.5))) (80.9 81.5)
, поскольку он также захватит последнее выражение.
Суть в том, что, как упоминалось выше, это задача не только для регулярных выражений.
Комментарии:
1. если существует много tan(x tan(x tan (x))), требование состоит в том, чтобы сначала получить самый внутренний tan
2. Вы не можете использовать только регулярные выражения для этого ! Но ваш вопрос все еще неясен.
Ответ №4:
Поскольку я не могу использовать операторы and
и not
отфильтровывать самые внутренние tan
, я, наконец, попробовал:
public String MatchExtra(string head, string extra)
{
string result = "";
if (!head.Contains(extra))
return head;
string criteria = extra "\([a-zA-Z0-9\.\ \-\*\/] \)";
MatchCollection match1 = Regex.Matches(head, criteria, RegexOptions.IgnoreCase);
foreach (Match bracket_match in match1)
{
if (bracket_match.Success)
{ // not finish if bracket have bracket
for (int y = 0; y < bracket_match.Captures.Count; y )
{
string a = bracket_match.Captures[y].ToString();
string b = bracket_match.Captures[y].ToString().Substring(extra.Length 1, bracket_match.Captures[y].ToString().Length - extra.Length - 2);
result = MatchExtra(bracket_match.Captures[y].ToString().Substring(extra.Length 1, bracket_match.Captures[y].ToString().Length - extra.Length - 2), extra);
return resu<
}
}
}
string criteria2 = extra "\(.*\)";
MatchCollection match2 = Regex.Matches(head, criteria, RegexOptions.IgnoreCase);
foreach (Match bracket_match in match2)
{
if (bracket_match.Success)
{ // not finish if bracket have bracket
for (int y = 0; y < bracket_match.Captures.Count; y )
{
string a = bracket_match.Captures[y].ToString();
string b = bracket_match.Captures[y].ToString().Substring(extra.Length 1, bracket_match.Captures[y].ToString().Length - extra.Length -2);
result = MatchExtra(bracket_match.Captures[y].ToString().Substring(extra.Length 1, bracket_match.Captures[y].ToString().Length - extra.Length-2), extra);
return resu<
}
}
}
return resu<
}