"역순"으로 가새 확장 적용


21

예를 들어로 {a..c}{1..3}확장됩니다 a1 a2 a3 b1 b2 b3 c1 c2 c3.

인쇄 a1 b1 c1 a2 b2 c2 a3 b3 c3하고 싶다면 비슷한 방법이 있습니까? 가장 간단한 방법은 무엇입니까?

답변:


30

당신은 할 수 있습니다 :

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

그런 다음 쉘에 평가하도록 지시합니다.

echo {a..c}1 {a..c}2 {a..c}3

10

이 특별한 경우에, 나는 Stéphane Chazelas 가 제공하는 옵션 이 최선 이라고 생각합니다 .

반면에 더 복잡한 것을 확장하면이 옵션이 제대로 확장되지 않습니다. 따라서 다음과 같이 똑같이 달성 할 수 있습니다.

$ printf '%s\0' {a..c}{1..3} | sort -zk 1.2,1.2 | tr '\0' ' '

다음을 반환합니다.

a1 b1 c1 a2 b2 c2 a3 b3 c3

조금 지저분 해 보이지만 지금은 위 명령에서 두 문자를 바꾸는 순서대로 제어 할 수 있습니다. 예를 들면 다음과 같습니다.

$ echo {a..b}{1..2}{a..b}{1..2}

이것은 다음으로 확장됩니다 :

a1a1 a1a2 a1b1 a1b2 a2a1 a2a2 a2b1 a2b2 b1a1 b1a2 b1b1 b1b2 b2a1 b2a2 b2b1 b2b2

1두 번째 확장에서 모든 것을 원한다고 가정 해보 십시오 2.

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.2,1.2 | tr '\0' ' '
a1a1 a1a2 a1b1 a1b2 b1a1 b1a2 b1b1 b1b2 a2a1 a2a2 a2b1 a2b2 b2a1 b2a2 b2b1 b2b2

a세 번째 확장에서 다음을 모두 원한다고 가정 해보 십시오 b.

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.3,1.3 | tr '\0' ' '
a1a1 a1a2 a2a1 a2a2 b1a1 b1a2 b2a1 b2a2 a1b1 a1b2 a2b1 a2b2 b1b1 b1b2 b2b1 b2b2

1네 번째 확장에서 다음을 모두 원한다고 가정 해보 십시오 2.

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.4,1.4 | tr '\0' ' '
a1a1 a1b1 a2a1 a2b1 b1a1 b1b1 b2a1 b2b1 a1a2 a1b2 a2a2 a2b2 b1a2 b1b2 b2a2 b2b2

나는 모든을한다고 가정 1a중간에, 다음 1b, 다음 2a, 다음 2b:

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -zk 1.2,1.3 | tr '\0' ' '
a1a1 a1a2 b1a1 b1a2 a1b1 a1b2 b1b1 b1b2 a2a1 a2a2 b2a1 b2a2 a2b1 a2b2 b2b1 b2b2

위의 확장에서 순서를 반대로 바꾸는 것만으로도 r이전 명령에를 추가 할 수 있습니다. 예를 들어, 마지막 것 :

$ printf '%s\0' {a..b}{1..2}{a..b}{1..2} | sort -rzk 1.2,1.3 | tr '\0' ' '
b2b2 b2b1 a2b2 a2b1 b2a2 b2a1 a2a2 a2a1 b1b2 b1b1 a1b2 a1b1 b1a2 b1a1 a1a2 a1a1

Note_1 : 일반적으로이 최종 확장이 인수 목록으로 사용될 경우 후행 공백은 문제가되지 않습니다. 그러나이를 제거하려면 위의 명령에 예를 들어 추가 할 수 있습니다| sed 's/ $//' . 또는 심지어| sed 's/ $/\n/'후행 공간을 변경하려면newline

Note_2 : 위의 예에서는개념 증명의 편의상두 요소의 하위 집합 (예 : {a, b} {1,2} )을 사용했습니다. 유한 길이의 하위 집합을 사용할 수 있습니다. 해당 명령은 비슷합니다.


5

bash, ksh, zsh

(bash, ksh, zsh)에서 작동하는 하나의 라이너 (일부 쉘이 "브레이스 확장"을 역순으로 수행 할 수있는 것은 아님) :

$ echo {3..1}{c..a} | rev
a1 b1 c1 a2 b2 c2 a3 b3 c3

사용하는 대안 eval(여전히 bash, ksh, zsh에 대해 더 암호로 사용될 수 있음)은 다음과 같습니다.

$ eval echo '{a..c}'{1..3}
a1 b1 c1 a2 b2 c2 a3 b3 c3

대체 무슨 이해하기 evalecho:

$ echo echo '{a..c}'{1..3}
echo {a..c}1 {a..c}2 {a..c}3

실행 된 명령 (eval 확장 후)은 실제로 echo {a..c}1 {a..c}2 {a..c}3입니다. 당신이 원하는대로 확장합니다.

모든 껍질

"괄호 확장"이없는 여러 쉘이 있으므로 "모든 쉘"에이를 사용할 수 없습니다. 루프가 필요합니다 (후행 공백이 있음).

$ for i in 1 2 3; do for j in a b c; do printf "%s%s " "$j" "$i"; done; done; echo
a1 b1 c1 a2 b2 c2 a3 b3 c3 

후행 공백을 추가하지 않아도되는 경우 :

s=""
for i in 1 2 3; do
    for j in a b c; do
        printf "%s%s%s" "$s" "$j" "$i"
        s=" "
    done
done
echo

인쇄물

a1 b1 c1 a2 b2 c2 a3 b3 c3

많은 값에 대해이 작업을 수행해야하는 경우 숫자 목록을 생성하기 위해 중괄호 확장과 유사한 것을 사용해야합니다 $(seq 10). 그리고 seq가 문자 목록을 생성 할 수 없으므로 생성 된 숫자를 ASCII로 변환해야합니다.

s=""
for i in $(seq 4); do
    for j in $(seq 5); do
        printf "%s\\$(printf %03o $((96+j)))%s" "$s" "$i"
        s=" "
    done
done
echo

인쇄물:

a1 b1 c1 d1 e1 a2 b2 c2 d2 e2 a3 b3 c3 d3 e3 a4 b4 c4 d4 e4

yash -o braceexpand목록에 추가 할 수도 있습니다 .
스테판 Chazelas

@ StéphaneChazelas 나는 확실하지 않다. 이 명령 은 Linux에서 yash -o braceexpand -c 'echo {3..1}{c..a}'인쇄합니다 3{c..a} 2{c..a} 1{c..a}. 완전한 "괄호 확장"이 아닙니다.
아이작

3
{a..c}1 {a..c}2 {a..c}3

의 중괄호 확장 {a..c}{1..3}은 왼쪽에서 오른쪽으로 확장되므로 먼저 a{1..3} b{1..3} c{1..3}문자를 얻은 다음 숫자와 숫자를 조합합니다 a1 a2 a3 b1 b2 b3 c1 c2 c3. 원하는 순서를 얻으려면 위의 약간 더 긴 표현을 사용해야합니다.


넓은 범위의 "숫자"에 대해 원한다면 더 이상 실용적이지 않습니다.
RUBEN GONÇALO MOROUÇO

3
@ RUBENGONÇALOMOROUÇO 아니요 그렇지 않습니다. 많은 수의 숫자로 수행하는 경우 이중 루프와 같은 대체 방법을 사용하는 것이 좋습니다. 그것은 수천 개의 조합에서 작동하는 반면, 중괄호는 특정 상황에서 "인수 목록이 너무 깁니다".
Kusalananda

2

루프 사용하기 :

for n in {1..3}; do printf '%s\n' {a..c}"$n"; done

첫 번째 확장을 반복 한 다음 두 번째 문자로 각 문자를 확장합니다.

한 줄에 모든 출력이 필요한 경우 다음을 제거 할 수 있습니다 \n.

for n in {1..3}; do printf '%s ' {a..c}"$n"; done

이것은 후행 줄 바꿈을 제공하지 않지만 문제가되지 않는 명령이나 변수에 전달하는 경우.


1
루프 솔루션에 대해 왜 그렇게 많은 투표권이 있습니까?
아이작

나는 질문을 잘못 읽었을 것이다. 업데이트
Jesse_b

2

이것은 간단한 경우에 효과적이며 확장 할 수는 있지만 빨리 벗어날 수 있습니다. 이것이 작동하지 않는 더 복잡한 경우는 구성하기 쉽습니다.

중괄호 확장 순서를 반대로 바꾼 다음 문자를 바꾸십시오.

echo {1..3}{a..c} | sed -E 's/(.)(.)( ?)/\2\1\3/g'

@muru : 죄송합니다. 결정된. 감사.
추후 공지가있을 때까지 일시 중지되었습니다.

@Isaac : 후행 공간을 수정했습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

0

간단한 방법 중 하나는 sort를 사용하는 것입니다 (1.2,1.2는 두 번째 위치에서 한 문자를 가져와 같은 위치에서 끝내는 것을 의미합니다).

$ for i in {a..c}{1..3}; do echo $i; done|sort -n -k1.2,1.2
a1
b1
c1
a2
b2
c2
a3
b3
c3

한 줄로 원하면 tr을 다음과 같이 사용할 수 있습니다.

$ for i in {a..c}{1..3}; do echo $i; done|sort -n -k1.2,1.2|tr '\n' ' '
a1 b1 c1 a2 b2 c2 a3 b3 c3

-2

아래 방법으로 완료

for i in {1..10}; do for j in {a..c}; do echo $j$i; done; done| perl -pne "s/\n/ /g"

산출

a1 b1 c1 a2 b2 c2 a3 b3 c3 a4 b4 c4 a5 b5 c5 a6 b6 c6 a7 b7 c7 a8 b8 c8 a9 b9 c9 a10 b10 c10

또한 고려for i in {1..10}; do for j in {a..c}; do printf '%s ' "$j$i"; done; done;echo
Jeff Schaller
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.