Строка переключения содержит или запускает [дубликат]

Различия в поведении

Протестировано в Bash 4.3.11:

  • POSIX vs Расширение Bash: [ - POSIX [[ is расширение Bash
  • регулярная команда vs magic [ - это просто регулярная команда со странным именем. ] - это просто аргумент [, который не позволяет использовать дополнительные аргументы. Ubuntu 16.04 фактически имеет исполняемый файл для него в /usr/bin/[, предоставленный coreutils, но встроенная версия bash имеет приоритет. Ничто не изменяется в том, как Bash анализирует команду. В частности, < является перенаправлением, && и || объединяют несколько команд, ( ) генерирует подоболочки, если не экранируется \, и расширение слова происходит, как обычно. [[ X ]] представляет собой единую конструкцию, которая делает X разыгранным магическим образом. <, &&, || и () обрабатываются специально, а правила разделения слов различны. Существуют также дополнительные различия, такие как = и =~. В Bashese: [ - встроенная команда, а [[ - ключевое слово: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and- shell-keyword
  • < [[ a < b ]]: лексикографическое сравнение [ a \< b ]: То же, что и выше. \, или же перенаправление, как и для любой другой команды. Расширение Bash. Я не мог найти альтернативу POSIX, см. . Как проверить строки для меньших или равных?
  • && и || [[ a = a && b = b ]]: true, logical и [ a = a && b = b ]: синтаксическая ошибка, && проанализирована как разделитель команды AND cmd1 && cmd2 [ a = a -a b = b ]: эквивалентна, но устарела POSIX [ a = a ] && [ b = b ]: рекомендация POSIX
  • ( [[ (a = a || a = b) && a = b ]]: false [ ( a = a ) ]: синтаксическая ошибка, () интерпретируется как подоболочка [ \( a = a -o a = b \) -a a = b ]: эквивалентна, но () устарела с помощью POSIX ([ a = a ] || [ a = b ]) && [ a = b ] Рекомендация POSIX
  • разбиение слова x='a b'; [[ $x = 'a b' ]]: true, кавычки не нужны x='a b'; [ $x = 'a b' ]: синтаксическая ошибка, расширяется до [ a b = 'a b' ] x='a b'; [ "$x" = 'a b' ]: эквивалентна
  • = [[ ab = a? ]]: true, потому что она соответствует шаблону (* ? [ являются волшебными). Не расширяет glob для файлов в текущем каталоге. [ ab = a? ]: a? glob расширяется. Так может быть истинным или ложным в зависимости от файлов в текущем каталоге. [ ab = a\? ]: false, а не расширение glob = и == одинаковы для обоих [ и [[, но == является расширением Bash. printf 'ab' | grep -Eq 'a.': эквивалент POSIX ERE [[ ab =~ 'ab?' ]]: false, теряет магию с помощью '' [[ ab? =~ 'ab?' ]]: true
  • =~ [[ ab =~ ab? ]]: true, расширенное регулярное выражение POSIX match, ? не glob expand [ a =~ a ]: синтаксическая ошибка printf 'ab' | grep -Eq 'ab?': эквивалент POSIX

Рекомендация

Я предпочитаю всегда использовать [].

Есть эквиваленты POSIX для каждой конструкции [[ ]], которую я видел.

Если вы используете [[ ]], вы:

  • потеряете переносимость
  • заставляют читателя изучать тонкости другого расширения bash. [ - это просто регулярная команда со странным именем, никакая специальная семантика не задействована.

7
задан Caverman 22 January 2016 в 18:22
поделиться

5 ответов

Вы переключаете String, а subArea.StartsWith() возвращает Boolean, поэтому вы не можете этого сделать. Я предлагаю вам сделать это следующим образом:

if (subArea.StartsWith("3*") || subArea.StartsWith("03*"))
    return "123";

switch(subArea)
{
    case "4100":
    case "4101":
    case "4102":
    case "4200":
        return "ABC";
    case "600A":
        return "XWZ";
    default:
        return "ABCXYZ123";
}

Результат будет таким же.

8
ответ дан appa yip yip 31 August 2018 в 19:56
поделиться

С помощью LINQ, хороший ответ by @seriesOne можно немного упростить, заменив операторы foreach и return на:

// using System.Linq;

// Look for a match...
var result = cases
    .Where(c => c.Item3(subArea, c.Item1))
    .FirstOrDefault();

// Return the match or the default.
return result == null ? "ABCXYZ123" : result.Item2;
2
ответ дан DavidRR 31 August 2018 в 19:56
поделиться

Просто для удовольствия, вот еще одно решение, которое позволяет избежать оператора switch.

var map = new[] {
    new { Value = "4100", StartsWith = false, Result="ABC" },
    new { Value = "4101", StartsWith = false, Result="ABC" },
    new { Value = "4102", StartsWith = false, Result="ABC" },
    new { Value = "4200", StartsWith = false, Result="ABC" },
    new { Value = "600A", StartsWith = false, Result="XWZ" },
    new { Value = "3*", StartsWith = true, Result="123" },
    new { Value = "03*", StartsWith = true, Result="123" },
};

var subarea = ... whatever ...;

var result = map.Where(e =>
        {
            if (e.StartsWith)
            {
                return subarea.StartsWith(e.Value);
            }
            else
            {
                return subarea == e.Value;
            }
        }
    )
    .Select(e => e.Result)
    .FirstOrDefault() ?? "ABCXZ123";

Порядок в массиве map определяет приоритет, так что, например, вы можете иметь точное соответствие на, скажем, «3 * 11», а также совпадение StartsWith на «3 *», например:

var map = new[] {
    new { Value = "3*11", StartsWith = false, Result="ABC" },
    new { Value = "4100", StartsWith = false, Result="ABC" },
    new { Value = "4101", StartsWith = false, Result="ABC" },
    new { Value = "4102", StartsWith = false, Result="ABC" },
    new { Value = "4200", StartsWith = false, Result="ABC" },
    new { Value = "600A", StartsWith = false, Result="XWZ" },
    new { Value = "3*", StartsWith = true, Result="123" },
    new { Value = "03*", StartsWith = true, Result="123" },
};
2
ответ дан Joe 31 August 2018 в 19:56
поделиться

Ярлыки case должны быть строками, так как выражение switch является строкой; однако StartsWith возвращает логическое значение. Я рекомендую обработать эти особые случаи в секции default.

switch(subArea)
{
    case "4100":
    case "4101":
    case "4102":
    case "4200":
        return "ABC";
    case "600A":
        return "XWZ";
    default:
        if (subArea.StartsWith("3") || subArea.StartsWith("03")) {
            return "123";
        }
        return "ABCXYZ123";
}

Также звезда (*), вероятно, ошибается, если вы не хотите, чтобы subArea содержал ее. StartWith не принимает подстановочные знаки.

В качестве альтернативы вы можете использовать regex:

if (Regex.IsMatch(subArea, "^3|^03")) { // or "^(3|03)"
    return "123";
}

, где ^ означает начало строки и | означает или .

3
ответ дан Olivier Jacot-Descombes 31 August 2018 в 19:56
поделиться

Джо меня избивает, но вот еще один способ, не связанный с переключением, который реализует алгоритм соответствия шаблону с набором правил.

private static string GetSomeStringOrOther(string subArea)
{
    // Create a set of pattern matching functions...
    Func<string, string, bool> matchEquals = (a, b) => a.Equals(b);
    Func<string, string, bool> matchStarts = (a, b) => a.StartsWith(b);

    // Create a rule set...
    Tuple<string, string, Func<string, string, bool>>[] cases = new []
    {
        new Tuple<string, string, Func<string, string, bool>>("4100", "ABC", matchEquals),
        new Tuple<string, string, Func<string, string, bool>>("4101", "ABC", matchEquals),
        new Tuple<string, string, Func<string, string, bool>>("4102", "ABC", matchEquals),
        new Tuple<string, string, Func<string, string, bool>>("4200", "ABC", matchEquals),
        new Tuple<string, string, Func<string, string, bool>>("600A", "XWZ", matchEquals),
        new Tuple<string, string, Func<string, string, bool>>("3*", "123", matchStarts),
        new Tuple<string, string, Func<string, string, bool>>("03*", "123", matchStarts),
    };

    // Look for a match...
    foreach(var matchCase in cases)
    {
        if(matchCase.Item3(subArea, matchCase.Item1))
        {
            // Return if it matches...
            return matchCase.Item2;
        }
    }

    // Otherwise return the default...
    return "ABCXYZ123";
}

Преимущества

  • Если вам нужно новое правило, его легко добавить в набор правил.
  • Если вам нужна новая функция сопоставления шаблонов, то ее легко добавить.
  • Недостатки

    • Новичок / Новичок и даже некоторые промежуточные разработчики могут не иметь понятия, что происходит.

    Усовершенствования

    • Замените Tuple<string, string, Func<string, string, bool>> семантическим объектом, который представляет Rule
2
ответ дан series0ne 31 August 2018 в 19:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: