단어로 변수 내용 뒤집기


13

변수가 있다면

VAR='10 20 30 40 50 60 70 80 90 100'

그리고 그것을 에코

echo "$VAR"
10 20 30 40 50 60 70 80 90 100

그러나 스크립트를 더 아래로 내리면이 변수의 순서를 반대로 바꿔서 다음과 같이 표시됩니다.

echo "$VAR" | <code to reverse it>
100 90 80 70 60 50 40 30 20 10

나는 rev를 사용해 보았고 문자 그대로 모든 것을 뒤집 었으므로

echo "$VAR" | rev
001 09 08 07 06 05 04 03 02 01

2
이 비슷한 질문에 대한 답변에서 유용한 제안을 찾을 수 있습니다 . IP 주소를 거꾸로 읽는 방법? (기간 대신 공간 구분 기호를 조정하기
만하면 됨

답변:


21

GNU 시스템에서 cat의 반대는 tac입니다.

$ tac -s" " <<< "$VAR "            # Please note the added final space.
100 90 80 70 60 50 40 30 20 10

건배! 그 트릭을했다. 나는 아직도 배울 것이 많다
Alistair Hardy

@JhonKugelman 에코가 없으면 출력에 다음과 같은 추가 줄 바꿈이 있습니다.echo $'100 \n90 80 70 60 50 40 30 20 10'
sorontar

현재 tac -s" " <<< "$VAR "버전에서는 여전히 빈 줄을 삽입하고 후행 공백을 추가하고 후행 줄 바꿈 문자를 생략합니다 ( printf '\n%s ' "$reversed_VAR"예상 대신 printf '%s\n' "$reversed_VAR")
Stéphane Chazelas

@don_crissti 원래의 대답 : IFS에 후행 줄 바꿈과 공백이 있으면 제거 echo $(tac -s" " <<< $VAR)하므로 후행 공백이 없습니다 $(…). 내 솔루션은 곧 수정 될 것입니다.
sorontar

6

짧은 목록과 변수의 경우 쉘 자체가 가장 빠른 솔루션입니다.

var="10 20 30 40 50 60 70 80 90 100"
set -- $var; unset a 
for ((i=$#;i>0;i--)); do
    printf '%s%s' "${a:+ }" "${!i}"
    a=1
done
echo

산출:

100 90 80 70 60 50 40 30 20 10 

참고 : 분할 작업 set -- $var은 여기에 사용 된 정확한 문자열에 안전하지만 문자열에 와일드 카드 문자 ( *, ?또는 []) 가 포함 된 경우에는 그렇지 않습니다 . set -f필요한 경우 분할 전에 피할 수 있습니다 . 다음 참고 사항에도 동일한 참고 사항이 적용됩니다 (표시된 경우 제외).

또는 반대 목록으로 다른 변수를 설정하려면 다음을 수행하십시오.

var="10 20 30 40 50 60 70 80 90 100"
set -- $var
for i; do out="$i${out:+ }$out"; done
echo "$out"

또는 위치 매개 변수 만 사용하십시오.

var="10 20 30 40 50 60 70 80 90 100"
set -- $var
a=''
for    i
do     set -- "$i${a:+ $@}"
       a=1
done
echo "$1"

또는 변수 하나만 사용할 수 있습니다 (var 자체 일 수 있음).
참고 :이 솔루션은 globing이나 IFS의 영향을받지 않습니다.

var="10 20 30 40 50 60 70 80 90 100"

a=" $var"
while [[ $a ]]; do
    printf '<%s>' "${a##* }"
    var="${a% *}"
done

2

awk 구조에

$ var='10 20 30 40 50 60 70 80 90 100'

$ echo "$var" | awk '{for(i=NF; i>0; i--) printf i==1 ? $i"\n" : $i" "}'
100 90 80 70 60 50 40 30 20 10


perl의례 IP 주소를 거꾸로 읽는 방법? 공유 @steeldriver

$ echo "$var" | perl -lane '$,=" "; print reverse @F'
100 90 80 70 60 50 40 30 20 10


또는 bash문자열을 배열로 변환하여 자체적으로

$ arr=($var)    
$ for ((i=${#arr[@]}-1; i>=0; i--)); do printf "${arr[i]} "; done; echo
100 90 80 70 60 50 40 30 20 10 

2

배열과 같은 bash 기능을 사용하여 완전히 처리 할 수 ​​있습니다.

#!/bin/bash
VAR="10 20 30 40 50 60 70 80 90 100"
a=($VAR); rev_a=()
for ((i=${#a[@]}-1;i>=0;i--)); do rev_a+=( ${a[$i]} ); done; 
RVAR=${rev_a[*]}; 

$ VAR이 그다지 크지 않다면 가장 빠른 방법입니다.


그러나 값에 와일드 카드 문자 (예 :)가 포함 된 변수에는 확장되지 않습니다 VAR='+ * ?'. 사용 set -o noglob또는 set -f그 문제를 해결합니다. 보다 일반적으로 $IFSsplit + glob 연산자를 사용할 때 globbing 의 가치 와 상태 를 고려하는 것이 좋습니다 . 아니 그것에서 그 연산자를 사용하는 거의 의미가 있음을 rev_a+=( ${a[$i]} ), rev_a+=( "${a[$i]}" )더 많은 의미가 없을 것입니다.
Stéphane Chazelas


1

여기에 약간의 파이썬 마술을 사용하십시오 :

bash-4.3$ VAR='10 20 30 40 50 60 70 80 90 100'
bash-4.3$ python -c 'import sys;print " ".join(sys.argv[1].split()[::-1])'  "$VAR" 
100 90 80 70 60 50 40 30 20 10

이것이 작동하는 방식은 매우 간단합니다.

  • 우리 "$VAR"는 두 번째 명령 줄 매개 변수라고합니다 sys.argv[1]( -c옵션이있는 첫 번째 매개 변수 는 항상-c 그 자체입니다. "$VAR"변수 자체를 개별 단어로 분리하지 않도록 인용 부호를 확인하십시오 (python이 아닌 shell에 의해 수행 됨)
  • 다음으로 우리는 .split() 메소드 하여 문자열 목록으로 나누십시오.
  • [::-1] 일부는 단지 목록의 반전을 위해 확장 된 슬라이스 구문 입니다.
  • 마지막으로 모든 것을 하나의 문자열로 결합 " ".join()하고 인쇄합니다.

그러나 큰 파이썬 팬이 아닌 사람들 AWK은 본질적으로 같은 일을 할 수 있습니다 : 배열을 반대로 나누고 인쇄하십시오 :

 echo "$VAR" | awk '{split($0,a);x=length(a);while(x>-1){printf "%s ",a[x];x--};print ""}'
100 90 80 70 60 50 40 30 20 10 

1
또는 다소 더 깨끗한python3 -c 'import sys;print(*reversed(sys.argv[1:]))' $VAR
iruvar

클리너가 아닌 @iruvar $IFS은 적절한 문자를 포함하지 않고 glob 부분을 비활성화 하지 않고 쉘의 split + glob 연산자를 호출합니다 .
Stéphane Chazelas

@ StéphaneChazelas, 충분히 사실-파이썬 부분은 여전히 ​​깨끗합니다 (IMHO). 따라서 "$VAR"수익률 로 돌아 가기python3 -c 'import sys;print(*reversed(sys.argv[1].split()))' "$VAR"
iruvar

1

zsh:

print -r -- ${(Oa)=VAR}

$=VAR에 분할 $VAR합니다 $IFS. (Oa)결과 목록을 역순으로 정렬합니다. print -r --(와 같이 ksh) echo -E -( zsh구체적으로) 와 같은 신뢰할 수있는 버전은echo 다음 같습니다. 인수를 공백으로 구분하여 줄 바꿈으로 종료하여 그대로 인쇄합니다.

$IFS포함 된 공간 (기본적으로 공백, 탭, 줄 바꿈, 널)이 아닌 공백만으로 분할 하려면 공백을에 할당 $IFS하거나 다음과 같은 명시 적 분할을 사용하십시오.

print -r -- ${(Oas: :)VAR}

역순으로 정렬하려면 :

$ VAR='50 10 20 90 100 30 60 40 70 80'
$ print -r -- ${(nOn)=VAR}
100 90 80 70 60 50 40 30 20 10

POSIXly (그래서도 작동합니다 bash) :

쉘 내장 ( printf일부 쉘 제외 ) 메커니즘 만 (짧은 값을 가진 변수의 경우) :

unset -v IFS # restore IFS to its default value of spc, tab, nl
set -o noglob # disable glob
set -- $VAR # use the split+glob operator to assign the words to $1, $2...

reversed_VAR= sep=
for i do
  reversed_VAR=$i$sep$reversed_VAR
  sep=' '
done
printf '%s\n' "$reversed_VAR"

와 함께 awk(더 큰 변수, 특히와 함께 bash하지만 인수 크기 (또는 단일 인수)의 크기 제한까지) :

 awk '
   BEGIN {
     n = split(ARGV[1], a);
     while (n) {printf "%s", sep a[n--]; sep = " "}
     print ""
   }' "$VAR"

0

우아한 POSIX 소프트웨어 툴 원 라이너 :

echo `echo $VAR | tr ' ' '\n' | sort -nr`
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.