Bash-Skript zum Wiederholen jedes Wortes in einer Zeile?

Bash-Skript zum Wiederholen jedes Wortes in einer Zeile?

Ich habe eine Zeichenfolge wie:dog cat bird whale

Und ich möchtedog dog cat cat bird bird whale whale

Alle Wörter stehen in derselben Zeile. Irgendeine Idee?

Antwort1

Ergänzung zur Lösungsfamilie :-) .

duplicator.sh:

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

Ausführbar machen, und jetzt:

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

Alternativ als Shell-Funktion, zB zur Wiederverwendung innerhalb eines Skripts:

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

die dann direkt ausgeführt werden können, wo definiert als

duplicator dog cat bird whale

Antwort2

Du könntest benutzen sed:

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

Wenn Sie die Änderungen an der Datei direkt speichern möchten, sagen Sie:

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

Sie könnten auch verwenden perl:

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

(Fügen Sie die -iOption hinzu, die Änderungen direkt an der Datei zu speichern.)

Oder, wie vorgeschlagen vonterdon:

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

Zitat ausperlvar:

@F

Das Array @Fenthält die Felder jeder Zeile, die eingelesen werden, wenn der Autosplit-Modus eingeschaltet ist. Informationen zum -aSchalter finden Sie unter perlrun. Dieses Array ist paketspezifisch und muss deklariert oder mit einem vollständigen Paketnamen versehen werden, wenn es sich bei der Ausführung unter nicht im Paket main befindet strict 'vars'.

Antwort3

Was wäre das ohne awk/gawkAntwort:

$ 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 

Wenn ein abschließender Zeilenumbruch wichtig ist:

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

Antwort4

Wenn sich Ihr String beispielsweise in einer Variablen befindet, foo="dog cat bird whale"können Sie Folgendes tun:

  • Reines 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
    

    Erläuterung:Die Klammern sind erforderlich, damit readund echoin derselben Subshell vorkommen und daher Variablen gemeinsam nutzen können. Ohne sie echowürde nur eine leere Zeile gedruckt.

  • Kernel-Dienstprogramme:

    $ 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
    

    Erläuterung:Mit dem -oFlag von joinkönnen Sie das Ausgabeformat festlegen. Hier sage ich, dass das erste Feld der ersten Datei ( 1.1) gedruckt werden soll, gefolgt vom zweiten Feld der ersten Datei ( 1.2) usw. Auf diese Weise wird jedes Feld der ersten Datei zweimal gedruckt. ist jedoch so joinkonzipiert, dass es, nun ja, verbindetzweiEingabezeilen in einem gemeinsamen Feld. Also übergebe ich auch eine leere Zeile ( <(echo)) und ignoriere sie dann. Das -jlegt das Verbindungsfeld fest. Wenn es auf ein nicht vorhandenes (das 5.) gesetzt wird, wird joindie gesamte Zeile gedruckt.

    Wenn Sie sich nicht um Leerzeichen oder die Eingabereihenfolge kümmern, können Sie Folgendes tun:

    $ 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
    

    Erläuterung:

    -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.
    

    Das obige Skript speichert jedes Feld (von @F) zweimal im Array @kund druckt dann @k. Wenn Sie den abschließenden Zeilenumbruch nicht benötigen, können Sie ihn vereinfachen zu

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

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

    Erläuterung:Die -0Option setzt das Trennzeichen für den Eingabedatensatz (als Hexadezimal- oder Oktalzahl, sieheHierfür Konvertierungen). Hier stelle ich es auf Oktal ein, 040was ein Leerzeichen ist. Dadurch -pwird perljede Eingabe „Zeile“ gedruckt und da wir den Datensatztrenner auf Leerzeichen eingestellt haben, werden Zeilen jetzt durch Leerzeichen definiert, sodass jedes Feld zweimal gedruckt wird.

  • awk:

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

    Erläuterung: NFist die Anzahl der Felder, daher geht das obige Skript jedes Feld durch und hängt es an sich selbst an. Sobald dies erledigt ist, drucken wir die Zeile ( 1;ist nur eine Abkürzung für Drucken).

verwandte Informationen