Как подсчитать количество расширений параметров, арифметических расширений и т. Д.? [закрыто]

Я новичок в написании сценариев на bash.

Попытка написать простой скрипт, который читает из стандартного ввода (файла) и записывает в стандартный вывод. Я хочу, чтобы сценарий подсчитывал количество параметров / арифметических расширений и замен команд.

Для стандартного ввода я пока делал следующее:

file=${1--}
while IFS= read -r line; do 
  printf '%s\n' "$line"
done < <(cat - "$file")
1
задан 4 December 2017 в 11:53

1 ответ

Практический способ

Просто используйте grep с флагом -c для подсчета, или еще лучше grep -o '<PATTERN>' | wc -l (см. Примечание об этом позже в тексте). В зависимости от того, как вы хотите, чтобы ваш вывод выглядел, и в зависимости от того, чего вы хотите достичь, существует несколько способов его настройки.

Конечно, существуют разные типы расширения параметров, поэтому нам нужно написать для них разные шаблоны. Здесь я только что написал замену шаблонов, удаление префиксов и арифметическое расширение, но вы можете адаптировать их к любому другому.

На самом базовом уровне мы можем вызывать отдельные команды так:

$ cat ./myscript.sh                                                         
#!/bin/bash

var="string"
echo "${var/string/thread}"
echo $((2+2))
echo $((3*2))

echo ${var#*i}
echo ${var##*i}

echo ${var%i*}
echo ${var%%i*}
$ grep -c '${.*}' myscript.sh                                               
1
$ grep -c '$((.*))' myscript.sh                                             
2

И это только основная идея. Вы можете поместить несколько grep паттернов в скрипт с хорошим начальным сообщением. Примерно так:

#!/usr/bin/env bash
printf "\nNumber of arithmetic expansions:"
grep -c '$((.*))' "$1"
printf "\nNumber of substitutions:"
grep -c '${.*\/.*\/.*}' "$1"
printf "\nNumber of prefix removals:"
grep -c '${.*[#]\{1,2\}.*}' "$1"

И затем вызвать этот скрипт как:

./count_bash_stuff.sh myscript.sh

Либо просто поместите все шаблоны в файл и вызовите grep с помощью -f. Конечно, он выведет только общее количество всех совпадений , а не отдельных:

$ cat ./patterns                                                            
$((.*))
${.*\/.*\/.*}
${.*[#]\{1,2\}.*}
$ grep -c -f ./patterns ./myscript.sh                                       
5

Примечание: как указал Steeldriver в комментарии под этим ответом, grep инструмент сопоставления строк, который означает, что если в строке более одного паттерна, он добавит 1 для подсчета только для этой линии. Лучше было бы использовать флаг -o с grep и направить вывод в wc -l. Таким образом, вместо этого мы могли бы сделать что-то подобное для арифметического расширения:

grep -o '$((.*))' |  wc -l

(не очень практичный) способ оболочки POSIX

Да, это возможно. Это сложно, но возможно с case утверждениями. Здесь я просто собираюсь написать case оператор для арифметического расширения и удаления самого длинного префикса. Остальное зависит от читателя, чтобы адаптироваться и расширяться.

1139 Опять же, имейте в виду, что это доказательство концепции. Обратите внимание, что здесь используется /bin/sh - в Ubuntu это POSIX-совместимая оболочка /bin/dash, а не bash.

#!/usr/bin/env sh
while IFS="" read -r line || [ -n "$line" ];
do
    case "$line" in
        # arithmetic expansion, appearing anywhere in line
        *'$(('*'))'*) arithmetic_count=$(($arithmetic_count+1));;
        *'${'*##*'}'* ) prefix_count=$((prefix_count+1));;
    esac
done < "$1"

echo "$arithmetic_count"
echo "$prefix_count"

И это выглядит так:

$ ./count_shell_stuff.sh myscript.sh                                                                                                                                   
2
1

Почему это не так практично, спросите вы? Потому что написание шаблонов в case может быть несколько сложным и немного сложнее, чем, скажем, в grep или Perl. Кроме того, вам придется написать case для каждой синтаксической структуры оболочки. С помощью grep или perl вы можете объединить несколько шаблонов в один. Но опять же, это только мое личное мнение. Сопоставление с строковым образцом все еще очень возможно, как я показал в этом небольшом доказательстве концепции, но я не рекомендовал бы это как способ.

2
ответ дан 4 December 2017 в 11:53

Другие вопросы по тегам:

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