Как я могу получить несколько входных данных от пользователя и преобразовать их в строку, которая ищет значения и добавляет их к переменной?

Вы можете :пометить стандартный вывод (с помощью НЕБУФЕРИРОВАННОГО sed, т. е. :sed -u...), сделать так, чтобы stderr также переходил на стандартный вывод (без тегов, поскольку он не проходил через этот тегирующий sed ), и, таким образом, иметь возможность различать 2 в результирующем файле журнала.

Следующее :является медленным(Его можно серьезно оптимизировать, используя, например, сценарий perl вместо while... ; do... ;done, например, это будет порождать подоболочки и команды в каждой строке! ), странно(кажется, мне нужны 2 этапа {}, чтобы в одном переименовать стандартный вывод, а затем в другом добавить к нему "проваленный" стандартный вывод )и т. д. Но это :" доказательство концепции ", которое попытается максимально сохранить порядок вывода stdout и stderr:

#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch

#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
#  to see if the order of stdout&stderr is kept

#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2 
touch existing existing2 existing3

#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs... 
                     # avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.

{
   { for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
   } | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
    case "$line" in
       ${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;; 
        *)            printf "%s\n" "$line"       >> out_AND_err.file ;;   
    esac; 
done;

# see the results:
grep "^" out.file out_AND_err.file
0
01.07.2021, 17:33
1 ответ

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

В итоге я не стал использовать оператор case, потому что оказалось, что, помещая все теги в массив, он не нужен.

#!/bin/bash

# dup stdout so we can print prompts etc in the ask function
# anything printed to >&3 will go to the terminal (i.e. original stdout)
# anything printed to stdout will be part of the function's return value
exec 3>&1

tags=( all
artifact1  artifact2  artifact3
artifact4  artifact5  artifact6
artifact7  artifact8  artifact9
artifact10 artifact11 artifact12
artifact13 artifact14 artifact15
)
declare -a deployment_tags
declare -a nums

# comment out or set to zero to disable debugging
debug=1

[ "$debug" = 1 ] && declare -p tags deployment_tags nums

###
### functions
###

print_choices() {
  i=1
  while [ "$i" -lt "${#tags[@]}" ] ; do
    # one per line
    #printf '%i. %s\n' "$i" "${tags[$i]}" >&3
    #let i=i+1

    # or three per line
    for j in 0 1 2; do
      [ -n "${tags[$i]}" ] && printf '%2i. %-12s\t' "$i" "${tags[$i]}" >&3
      let i=i+1
    done
    printf "\n" >&3

  done
}

usage() {
   echo "Usage: $(basename "$0") [n...]"
   echo
   print_choices
   echo "Choose 1 or more, separated by spaces or commas, or 0 for all of the above"
   exit 1;
}

ask() {
  echo "Enter the number of the artifacts you would like to deploy:" >&3
  print_choices
  echo "Choose 1 or more, separated by spaces or commas, 0 for all, or q to quit" >&3

  until [[ "$num" =~ ^[[:space:]0-9,qQ]+$ ]] ; do
    read -r -p "Choose: " num >&3

    [[ $num =~ [qQ] ]] && return 1

    # split into nums array.  if num contains zero ("all"), remove
    # all other choices as they're already included in "all"
    nums=( $(printf '%s' "$num" | sed -e 's/.*0.*/0/; s/,/ /g') )

    # if any of the numbers provided didn't correspond to a valid
    # tag, ask again
    for i in "${nums[@]}" ; do
      [ -z "${tags[$i]}" ] && echo "Invalid choice $i" >&3 && num=""
    done
  done

  echo "${nums[@]}"
}

updateArtifacts() {
   # WTF is the `--tags` argument to `cp`???
   # echo it because it's bogus
   echo cp -r /path/to/artifact/artifact.zip --tags "$@"

  # this function should do something useful with "$@".
}

###
### main code
###

# get the args from the command line, or ask for them if missing.
if [ -n "$*" ] ; then
  # only digits separated by commas or spaces allowed
  [[ "$*" =~ ^[[:space:]0-9,]+$ ]] || usage

  # split into nums array.  if num contains zero ("all"), remove
  # all other choices as they're already included in "all"
  nums=( $(printf '%s' "$*" | sed -e 's/.*0.*/0/; s/,/ /g') )
else
  nums=( $(ask) )
  [ "$?" != 0 ] && echo "Quitting..." && exit 0
fi

[ "$debug" = 1 ] && declare -p nums

# get nums choices into deployment_tags array
for i in "${nums[@]}" ; do
  [ -z "${tags[$i]}" ] && echo "Error: tag $i does not exist!" && exit 2

  deployment_tags+=("${tags[$i]}")
done

[ "$debug" = 1 ] && declare -p deployment_tags

updateArtifacts "${deployment_tags[@]}"
0
28.07.2021, 11:21

Теги

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