行内のすべての単語を繰り返すBashスクリプト?


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
シェルアプローチのシンプルさが気に入っています。
ヘンクランゲベルド14年

さて、私は本当にこのソリューションのシンプルさが大好きです
クリスティアン

最初に考えた方法よりもずっと良い方法です。
ジョー14年

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 14年

2
これはBashスクリプトではありません。(Bashシェルからでも)何らかのコマンドを呼び出しても、Bashスクリプトは構成されません。
ピーターモーテンセン14年

4
@PeterMortensenあなたは技術的には正しい(最良の種類の正しい)が、bashがインストールされている実際にはすべてのシステムには、sedやawkを含む標準のUNIXツールもあります。シェルスクリプティングのポイント(まあ、そのポイントの大部分)は、コマンドを適切な場所に向けることです。
evilsoup 14年

3
@PeterMortensenこれは誤りです。bashスクリプトは外部コマンドを呼び出すことができます。bashスクリプトはシェバン行で開始する必要がありますが、これは厳密には必要ありません。質問では、bashスクリプトが外部コマンド(多くの場合「純粋なbashスクリプト」と呼ばれる)を呼び出さないように指定していません。
ジル 'SO-悪であるのをやめる' 14年

2
素敵なperlトリック。短くすることができます-aperl -M5.10.0 -ane 'say join " ", map{$_, $_} @F;'
14年

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 14年

私のダウン票でfor(i=1;i<=NF;++i) printf "%s %s ",$i,$i;はありませんが、より短くて読みやすいです。
リチ14年

それについて議論するのは難しいので、アプローチを変更せずに私の答えを単純化して短縮しました(現在はインデックスが整数に切り捨てられていることを利用しています)。うまくいけば、より明確になります。
user19087 14年

1
これはBashスクリプトではありません。(Bashシェルからでも)何らかのコマンドを呼び出しても、Bashスクリプトは構成されません。
ピーターモーテンセン14年

ただし、これをスクリプトに入れるのは簡単です。
ケビン14年


1

たとえば、変数に文字列がある場合foo="dog cat bird whale"、次のようにできます。

  • 純粋なbash:

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

    説明:括弧がそのようにすることを必要としているreadecho同じサブシェルで起こるため、変数を共有することができます。それらがなければ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.1)に続いて1番目のファイルの2番目のフィールド(1.2)などを印刷するように指示しています。そのように、1番目のファイルの各フィールドが2回印刷されます。ただし、共通フィールドの2つの入力行をjoin結合するように設計されています。そのため、空行()を渡して無視します。セット原因が存在しないもの(第5回)に設定すると、フィールドに参加行全体を印刷します。<(echo)-jjoin

    空白や入力順序を気にしない場合は、行うことができます

    $ paste <(echo $foo) <(echo $foo)
    dog cat bird wale   dog cat bird wale
  • Perl 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)を配列に2回保存してから@k印刷します@k。末尾の改行が必要ない場合は、次のように単純化できます。

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

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

    説明:この-0オプションは、入力レコード分離文字を設定します(16進数または8進数として、変換についてはこちらを参照してください)。ここ040では、スペースである8進数に設定しています。これ-pにより、perl各入力が「行」で印刷され、レコード区切り文字がスペースに設定されたため、行はスペースで定義されるようになり、すべてのフィールドが2回印刷されます。

  • 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

標準入力から:

$ 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に組み込まれたシェル(テストtype echo)です。
ダニエルアンダーソン14年

@DanielAndersson:確かに、私は「書いた理由ですまた、心の中であなたの素敵な(すでに+ +1)答えを持つ、唯一のbashの組み込みコマンドを使用して」。
mpy 14年

OK、私のコメントを言語の混乱として分類できます:-)。
ダニエルアンダーソン14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.