한 줄에 모든 단어를 반복하는 배쉬 스크립트?


13

나는 다음과 같은 문자열을 가지고있다 : dog cat bird whale

그리고 나는 얻고 싶다 dog dog cat cat bird bird whale whale

모든 단어는 같은 줄에 있습니다. 어떤 생각?

답변:


28

솔루션 제품군에 추가 :-).

duplicator.sh:

for i; do echo -n "$i $i "; done; echo

실행 가능하게 만들고 지금 :

$ ./duplicator.sh dog cat bird whale
dog dog cat cat bird bird whale whale

대안 적으로 쉘 함수로서, 예를 들어 스크립트 내에서 재사용 가능 :

duplicator() {
    for i; do echo -n "$i $i "; done; echo
}

그런 다음 다음과 같이 정의 된 위치에서 직접 실행할 수 있습니다.

duplicator dog cat bird whale

4
나는 쉘 접근의 단순함을 좋아한다.
Henk Langeveld

글쎄, 나는이 솔루션의 단순함을 정말 좋아합니다.
Cristian

내가 생각한 첫 몇 가지 방법보다 낫다.
Joe

21

당신은 사용할 수 있습니다 sed:

sed -r 's/(\S+)/\1 \1/g' filename

파일의 변경 사항을 제자리에 저장하려면 다음과 같이 말하십시오.

sed -i -r 's/(\S+)/\1 \1/g' filename

당신은 또한 사용할 수 있습니다 perl:

perl -M5.10.0 -ne 'say join " ", map{$_, $_} split " ";' filename

-i변경 사항을 파일에 저장 하려면 옵션을 추가하십시오 .

또는 terdon이 제안한 대로 :

perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;' filename

인용 perlvar:

@F

배열 @F에는 자동 분할 모드가 켜져있을 때 읽은 각 줄의 필드가 포함됩니다. -a스위치 는 perlrun을 참조하십시오 . 이 배열은 패키지마다 다르며에서 실행될 때 main 패키지에없는 경우 선언되거나 전체 패키지 이름을 지정해야합니다 strict 'vars'.


4
더 짧음 : sed -r 's/\S+/& &/g'.
cYrus

2
Bash 스크립트가 아닙니다. Bash 쉘 에서조차 일부 명령을 호출해도 Bash 스크립트는 구성되지 않습니다.
피터 Mortensen

4
@PeterMortensen 기술적으로는 정확하지만 (가장 좋은 종류) 올바른 bash가 설치된 모든 시스템에는 sed 및 awk를 포함한 표준 유닉스 도구도 있습니다. 쉘 스크립팅의 전체 요점 (글쎄요, 요점의 상당 부분)은 올바른 위치에 명령을 지시하는 것입니다.
evilsoup

3
@PeterMortensen 잘못되었습니다. bash 스크립트는 외부 명령을 호출 할 수 있습니다. bash 스크립트는 shebang 줄로 시작해야하지만 꼭 필요한 것은 아닙니다. 질문은 bash 스크립트가 외부 명령을 호출하지 않아야한다는 것을 지정하지 않았습니다 (종종“순수한 bash 스크립트”라고 함).
Gilles 'SO- 악의를 멈춰라'

2
좋은 펄 트릭. 당신은 그것을 더 짧게 만들 수 있습니다 -a:perl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
terdon

4

awk/gawk대답 이없는 것은 무엇입니까?

$ awk '{ for(i=1;i<=NF+1;i+=1/2) { printf("%s ",$i); }}' <<<"dog cat bird whale"
dog dog cat cat bird bird whale whale 

종료 개행이 중요한 경우 :

$ awk '{ for(i=1;i<=NF+1;i+=1/2) { printf("%s ",$i); }} END{print ""}' <<<"dog cat bird whale"

내 첫 다운 보트. 왜 궁금한가요? 스크립트에 문제가 있습니까? 아니면 더 약식 버전?
user19087

내 공감대는 아니지만 for(i=1;i<=NF;++i) printf "%s %s ",$i,$i;더 짧고 읽기 쉬운 IMHO입니다.
rici

그것에 대해 논쟁하기가 어렵 기 때문에 접근법을 변경하지 않고 답변을 단순화하고 단축했습니다 (이제 인덱스를 정수로 반올림하는 이점을 얻습니다). 바라건대 이제 더 명확 해졌습니다.
user19087

1
Bash 스크립트가 아닙니다. Bash 쉘 에서조차 일부 명령을 호출해도 Bash 스크립트는 구성되지 않습니다.
피터 Mortensen

그러나 이것을 스크립트에 넣는 것은 쉽지 않습니다.
Kevin

3
s="dog cat bird wale"
ss=$( tr ' ' '\n' <<< "$s" | sed p | tr '\n' ' ' )
echo "$ss"
dog dog cat cat bird bird wale wale 

1
나는 글쓰기에 대해 sed -n 'p;p'생각했습니다. 그것이하는 일에 대해 더 투명하다고 생각했습니다.
glenn jackman

1
답변에 추가해야합니다!
terdon

1

변수에 문자열이있는 경우 다음과 같이하십시오 foo="dog cat bird whale".

  • 순수한 배쉬 :

    $ echo "$foo" | (read a b c d && echo "$a $a $b $b $c $c $d $d")
    dog dog cat cat bird bird whale whale

    설명 : 괄호가 너무 필요 read하고이 echo같은 서브 쉘에서 일어날 수 있으므로 공유 변수. 그것들이 없으면 echo빈 줄만 인쇄합니다.

  • coreutils :

    $ join -j 5 -o 1.1,1.1,1.2,1.2,1.3,1.3,1.4,1.4 <(echo $foo) <(echo)
    dog dog cat cat bird bird whale whale

    설명 :-o 의 플래그 join는 출력 형식을 설정할 수 있습니다. 여기서는 첫 번째 파일의 첫 번째 필드 ( 1.1) 를 인쇄 한 다음 첫 번째 파일 의 두 번째 필드 ( 1.2) 등 을 인쇄하도록 지시 합니다. 이렇게하면 첫 번째 파일의 각 필드가 두 번 인쇄됩니다. 그러나 공통 필드에서 두 개의 입력 라인을 join결합하도록 설계되었습니다 . 따라서 빈 줄 ( )을 전달한 다음 무시합니다. 설정합니다은 원인이 존재하지 않는 하나 (5)로 설정, 필드에 가입 전체 라인을 인쇄 할 수 있습니다.<(echo)-jjoin

    공백이나 입력 순서에 신경 쓰지 않으면 할 수 있습니다

    $ paste <(echo $foo) <(echo $foo)
    dog cat bird wale   dog cat bird wale
  • 펄 1 :

    $ echo $foo | perl -lane 'push @k, $_,$_ for @F; print "@k"'
    dog dog cat cat bird bird whale whale

    설명:

    -l: adds a newline to each print call (among other things)
    -a: turns on field splitting, fields are saved as @F
    -n: process input line by line
    -e: give a script as a command line parameter.

    위의 스크립트는 각 필드를 (부터 @F) 배열에 두 번 저장 @k한 다음 인쇄 @k합니다. 후행 줄 바꿈이 필요하지 않으면 다음과 같이 단순화 할 수 있습니다.

    $ echo $foo | perl -ane 'print " $_ $_" for @F'
  • 펄 2 :

    $ echo $foo | perl -0040 -pne 'print "$_"' | paste - - 
    dog dog cat cat bird bird whale whale

    설명 :-0옵션은 입력 레코드 구분 기호를 16 진수 또는 8 진수로 설정합니다 ( 변환 은 여기 참조 ). 여기에서는 040공백 인 8 진수로 설정합니다 . -p브랜드는 perl각 입력 "라인을"인쇄 우리는 공간 레코드 분리를 설정 한 이후 모든 필드 회 인쇄 있도록 라인은 이제 공백으로 정의된다.

  • awk:

    $ echo $foo | awk '{for(i=1;i<=NF;i++){$i=$i" "$i;} 1;}'
    dog dog cat cat bird bird whale whale

    설명 : NF 은 필드 수이므로 위의 스크립트는 각 필드를 거치면서 필드를 추가합니다. 완료되면, 우리는 라인을 인쇄합니다 (인쇄의 1;약어 일뿐입니다).


0

이제 python답을 찾으십시오.

명령 행에서 :

$ python -c "import sys; s=sys.argv[1:]; print(' '.join(j for i in zip(s,s)for j in i));" dog cat bird whale

stdin에서 :

$ python -c "s=input().split(); print(' '.join(j for i in zip(s,s)for j in i));" <<<"dog cat bird whale"

두 경우 모두 결과 :

dog dog cat cat bird bird whale whale

0

약간 정상이지만 haskell대답 :

$ ghc -e "getLine >>= putStrLn . unwords . (concatMap $ replicate 2) . words" <<<"dog cat bird whale"
dog dog cat cat bird bird whale whale

0

bash 내장 만 사용하는 또 다른 접근법

$ string="dog cat bird whale"
$ twix() { while [[ ! -z $1 ]]; do printf "%s %s " $1 $1; shift; done; }
$ twix $string
dog dog cat cat bird bird whale whale

상단 답변과 비교하여 어떤 이점도 보지 못하고 약간 다른 방법을 보여 주면 어떤 목적에 더 적합 할 수 있습니다.


echo또한 Bash (test type echo)에 내장 된 쉘 입니다.
Daniel Andersson

@DanielAndersson : 물론, 나는 " 또한 이미 bash 내장을 사용한다 "라고 썼습니다 .
mpy

좋아, 내 의견을 언어 혼란 :-)으로 분류 할 수 있습니다.
Daniel Andersson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.