사용자의 입력은 공백으로 구분하고 이러한 입력을 쉼표로 구분하는 명령에 입력해야 합니다.

사용자의 입력은 공백으로 구분하고 이러한 입력을 쉼표로 구분하는 명령에 입력해야 합니다.

그래서 공백으로 구분된 문자열이나 값을 입력한 다음 값을 하나씩 확인하고 이를 내가 가지고 있는 명령 중 하나에 필요한 형식으로 변환하는 사용자로부터 입력을 받을 수 있기를 원합니다. 나는 다음과 같은 것을 원합니다.

사용자는 다음과 유사한 프롬프트를 받게 됩니다.

Specify the package: perl runtime pool tools

저는 4개 문자열만 입력합니다. 이제 내 출력에 대해 다음과 같은 것을 원합니다.

Pkg1=perl,Pkg2=runtime,Pkg3=pool,Pkg4=tools

Pkg는 기본적으로 사용자가 입력한 금액을 기준으로 1씩 증가합니다.

가능합니까? Bash에서 어떻게 이를 달성할 수 있나요?

어떤 도움이라도 대단히 감사하겠습니다! 시간 내 주셔서 감사합니다!

답변1

첫 번째메시지 표시 안함! 데이터를 묻는 메시지를 표시하는 것은 좋은 생각이 아닙니다. 실수하기 쉽고, 철자가 틀리거나, 명령을 반복할 수 없고, 파일 이름에 탭 완성 기능을 사용할 수 없습니다. 이는 아무 이유 없이 사용자와 귀하의 삶을 더욱 어렵게 만들 뿐입니다. 사용자가 패키지 이름을 매개변수로 전달하도록 하세요.

#!/bin/bash

packageString="Pkg1=$1"
shift

for (( i=1; i<=$#;i++)); do
  packageString+=";Pkg"$((i+1))"=${!i}"
done
echo "$packageString";

질문에 대한 입력을 사용하여 위 스크립트를 실행하면 다음과 같은 결과가 나타납니다.

$ foo.sh perl runtime pool tools
Pkg1=perl;Pkg2=runtime;Pkg3=pool;Pkg4=tools

답변2

나는 울려퍼지고 있다테든스의 주장아무 이유 없이 사용자에게 대화형으로 메시지를 표시하지 마세요. 이 경우 사용자는 셸의 명령줄 기록에서 명령을 호출하거나 셸의 탭 완성, 일반 편집 기능 등을 사용할 수 있는 옵션을 제공하므로 문자열을 스크립트에 인수로 더 쉽게 제공할 수 있습니다.

다음 스크립트는 단일 awk명령을 사용합니다.

awk명령은 주어진 문자열을 명령줄 인수로 사용하고 루프에서 각 문자열의 형식을 개별적으로 지정합니다. 루프의 목적은 각각 문자열인 필드 레코드를 작성하는 것입니다. 여기서 PkgN=somethingN정수 카운터이고 something는 주어진 문자열 중 하나입니다.

루프가 끝나면 print전체 레코드가 출력됩니다. 필드 사이에는 에 할당된 구분 기호가 OFS사용됩니다.

#!/bin/sh

awk -v OFS=, '
BEGIN {
        for (i = 1; i < ARGC; ++i) $i = sprintf("Pkg%d=%s", i, ARGV[i])
        print
}' "$@"

같은 아이디어이지만 쉘 루프를 사용합니다.

#!/bin/sh

i=0
for pkg do
    i=$(( i + 1 ))
    set -- "$@" "Pkg$i=$pkg"
    shift
done

IFS=,
printf '%s\n' "$*"

그러면 각 위치 인수(스크립트 인수)가 새 문자열로 바뀌고 모두 쉼표를 구분 기호로 사용하여 인쇄됩니다.

인수가 지정되지 않으면 두 스크립트 모두 빈 줄을 출력합니다. 스크립트 시작 부분에서 매개변수를 테스트하고 매개변수가 없으면 종료하여 이를 방지할 수 있습니다.

[ "$#" -ne 0 ] || exit

여기서 테스트가 수행되는 방식은 스크립트가 인수 없이 호출되는 경우 스크립트가 0이 아닌 종료 상태로 종료되도록 보장합니다.

시험:

$ ./script perl runtime pool tools
Pkg1=perl,Pkg2=runtime,Pkg3=pool,Pkg4=tools

답변3

script.sh다음 코드(아래 예에 이름 지정)가 포함된 스크립트는 설명된 출력을 제공해야 합니다.

#!/bin/bash

#USER INPUT
read -p "Specify the package: " -a vals

#COUNTER
i=1

#ARRAY ELEMENT LOOP
for v in "${vals[@]}"; do

   #Printing output  
   echo -n "Pkg$i=$v"

   #Increment counter and add the comma, or break out of loop if $i==
   i=$((i+1))
   if [[ $i -le ${#vals[@]} ]]; then
        echo -n ","
   else
        break
   fi

done

셸에서 스크립트를 실행하려면 먼저 스크립트를 실행 가능하게 만든 chmod다음( ) 실행해야 합니다.

chmod +x script.sh
./script.sh

입력/출력은 다음과 같습니다.

Specify the package: perl runtime pool tools
Pkg1=perl,Pkg2=runtime,Pkg3=pool,Pkg4=tools

답변4

$ perl -le 'print join ",", map { "Pkg" . ++$i . "=$_" } @ARGV' perl runtime pool tools
Pkg1=perl,Pkg2=runtime,Pkg3=pool,Pkg4=tools

map { "Pkg" . ++$i . "=$_" } @ARGVPkg$i각 요소가 리터럴 문자열, 카운터 변수( )(각 루프에서 자동으로 증가됨) 및 리터럴 기호가 map앞에 붙은 명령줄 인수 중 하나 인 목록을 반환합니다 =. perldoc -f map작동 방식에 대한 자세한 내용은 를 참조하세요.

목록은 구분 기호로 쉼표로 연결된 다음 인쇄됩니다. 바라보다 perldoc -f join.

-l옵션을 사용하면 자동 줄 끝 처리가 가능해집니다. 이 스크립트의 경우 처리할 표준 입력이 없기 때문에 이는 모든 print명령문이 자동으로 개행 문자를 출력한다는 것을 의미합니다(일반적으로 Perl은 print명시적으로 포함하지 않는 한 개행 문자를 출력하지 않습니다). 보기 man perlrun-l\[octnum\]검색


사용자 입력을 먼저 수락하려면(다른 사람들이 지적했듯이 사용자에게 매우 짜증나고 불편하기 때문에 권장되지 않음) 다음을 사용하여 수행할 수 있습니다.

#!/bin/bash

# read the user input into array variable "$input"
read -p "Specify the package: " -r -a input

# now pass the array to the perl one-liner
perl -le 'print join ",", map { "Pkg" . ++$i . "=$_" } @ARGV' -- "${input[@]}"

이는 --사용자가 실수로 (또는 악의적으로) perl 명령줄 옵션과 같은 것을 입력하는 경우 perl이 사용자 입력을 옵션으로 해석하는 것을 방지합니다 -e ';system("rm -rf /");'. 사용자가 제공한 입력을 절대 신뢰하지 마세요.

그리고 평소와 같이 Perl 스크립트의 출력을 다른 쉘 변수로 캡처해야 하는 경우 다음을 사용하십시오.명령 대체:

var=$(perl -le 'print join ",", map { "Pkg" . ++$i . "=$_" } @ARGV' -- "${input[@]}")
printf "%s\n" "$var"

관련 정보