Проверьте, если номера из командной строки являются полномочиями 2

Кажется, я понял - спасибо.

С расширенным regexp для обработки дополнительных символов в N немного проще (обратите внимание, что пример ввода, используемый здесь, немного отличается от вашего собственного в вопросе):

sed -Ee's|([sio=%]..)?([@!T()^$/].)? *|\1\2|g' \
<<""
:
$ $ $N
$  $  $a
sa  s    l r
*56 l r
o1 o 2
%%xv

:
$ $ $N
$ $ $a
sa s  lr
*56lr
o1 o 2
%%xv

Вам понадобится GNU/BSD/AST sed, чтобы использовать это. Эквивалентный BRE будет выглядеть так:

sed 's|\([soi=%]..\)\{0,1\}\([@!T()^$/].\)\{0,1\} *|\1\2|g'

Хитрость заключается в том, чтобы сделать все совпадения в конечном итоге необязательными - так, чтобы ни одна часть шаблона не имела приоритета. Поскольку вы фактически только удаляете данные, а не вставляете (что должно обрабатываться совсем по-другому), у вас не будет никаких проблем с совпадениями для нулевых строк в промежутке между вашими целями совпадений. Кого волнует, сколько нулевых строк будет удалено? Регекс

sed сканирует пространство шаблона глобально и слева направо. Если бы существовала возможность перекрытия между совпадениями, он бы не работал очень хорошо, потому что он не возвращается назад в глобальном направлении. Но для этого есть только один случай, который я могу вспомнить, и он решен здесь. В любом случае, пространство всегда находится справа, и всегда есть некоторое не пространство слева. Однако возможно, что N может быть одним из названных вами односимвольных делителей, но в этом случае пробел сохраняется, как и должно быть.

По мере сканирования он сверяет вводимые данные с шаблонами - первым может быть 3-символьный, вторым - 2-символьный, а третьим - одиночный пробел (хотя это совпадение может продолжаться на любую длину).

При обнаружении любого из них sed либо заменит одно из первых двух совпадений на себя - например, passover, - но третье удалит полностью. И за один раз.

-5
23.11.2018, 00:41
6 ответов
$ is_power_of_two(){ printf '%x' "$1" | grep -q '^[1248]0*$'; }
$ powers_of_two(){ printf '%#x\n' "$@" | grep '^0x[1248]0*$' | xargs -I@ printf '%d\n' @; }

$ powers_of_two `seq 1 1000000`
1
2
4
8
16
32
64
128
...

В некоторых системах (, например. busybox)xargsне поддерживает стандартную опцию -I, но поддерживает опцию GNU-r(не запускать, если пусто ):

powers_of_two(){ test "$1" && printf '%#x\n' "$@" | grep '^0x[1248]0*$' | xargs -r printf '%d\n'; }
0
28.01.2020, 05:20

Число является степенью двойки, если его вес Хэмминга точно равен 1.

Вычислить вес Хэмминга числа — это то же самое, что вычислить количество единиц в его двоичном представлении.

Ниже приведен короткий bashскрипт, который делает это:

#!/bin/bash

# loop over all numbers on the command line
# note: we don't verify that these are in fact numbers
for number do
    w=0         # Hamming weight (count of bits that are 1)
    n=$number   # work on $n to save $number for later

    # test the last bit of the number, and right-shift once
    # repeat until number is zero
    while (( n > 0 )); do
        if (( (n & 1) == 1 )); then
            # last bit was 1, count it
            w=$(( w + 1 ))
        fi

        if (( w > 1 )); then
            # early bail-out: not a power of 2
            break
        fi

        # right-shift number
        n=$(( n >> 1 ))
    done

    if (( w == 1 )); then
        # this was a power of 2
        printf '%d\n' "$number"
    fi
done

Тестирование:

$ bash script.sh xyzdf 4 8 12 -2 USAD
4
8

Примечание. :Есть более эффективные способы сделать это, и bashособенно плохой выбор языка для этого.


Поскольку это всплывает несколько раз за короткое время (, это похоже на домашнее задание или какое-то другое упражнение):

  • Я не буду изменять этот код, чтобы пропустить число 1, если оно встречается во входных данных.
  • Я не заставлю его выводить сумму чисел в любой форме.
  • Не буду описывать алгоритм дальше того, что уже сделано в комментариях.
7
28.01.2020, 05:20

Еще один чистый подход bash

isPowerOf2 () {
    local n=$1 i=0
    for ((; n>1; n/=2, i++)); do :; done
    (($1 - (2 ** $i) == 0))
}

и

$ for n in {1..17}; do isPowerOf2 $n && echo $n; done
1
2
4
8
16

Или глядя на восьмеричное представление числа:

isPowerOf2() {
    local octal=$(printf %o "$1" 2>/dev/null) && 
      [[ $octal -eq 4 || $octal =~ ^[12]0*$ ]]
}

Или, может быть,

$ seq 17 | awk '{lg = log($1) / log(2)} lg == int(lg)'
1
2
4
8
16
4
28.01.2020, 05:20

Есть хороший способ проверить, является ли число степенью двойки.

Если вы представляете такое число в двоичном виде, это будет одна единица, за которой следует строка нулей, например, 0b100000для числа 32. Если вы вычтете из него единицу, вы получите единицы там, где раньше нули и ноль там, где у вас была 1, например 0b011111для числа 31, что равно 32 -1. Если вы выполните побитовую операцию и над этими двумя, вы получите ноль. Это свойство действительно только для чисел, которые являются степенью двойки (и нуля ).

Так:

function is_power_of_two () {
    declare -i n=$1
    (( n > 0 && (n & (n - 1)) == 0 ))
}

Использовать как:

for number; do
    if is_power_of_two "$number"; then
        printf "%d\n" "$number"
    fi
done

И вывод выполнения:

$./power2.sh 1 2 3 4 5 7 8 9 31 32 33 -2
1
2
4
8
32
14
28.01.2020, 05:20

Получили команду factor? Попробуйте

factor $number | sed 's/^[^:]*:\|[2 ]//g;'

и проверить пустой результат.

2
28.01.2020, 05:20

Если только для bash, то должно работать:

#!/bin/bash
powers_of_two(){
    sum=0
    for n                          # for every argument from the command line.
    do

    [[ $n =~ ^0*([0-9]+)$ ]] ||    # check that the argument only has base 10 digits.
        continue                   # If not go to next number.

    n=${BASH_REMATCH[1]}           # Remove all of the leading zeros.

    (( n>0 && !(n&(n-1)) )) &&     # Is n positive and a power of 2.
        printf '%d %d\n' "$n" "$((sum+=n))"        # print the number
                                                   # and the sum as integer
                                                   # numbers in base 10.

    done
}


powers_of_two -22 0 1 2 3 4 5 7 8 08 00008 9 31 32 33 -2 asd fhgh 2+2 3e3 inf

При выполнении:

$./script
1 1
2 3
4 7
8 15
8 23
8 31
32 63
0
28.01.2020, 05:20

Теги

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