:
est un autre nom pour true
. Les deux sont des commandes shell dans bash, mais non /bin/:
, seulement un /bin/true
. La redirection de sortie entraîne le shell dans open(2)
le fichier avec O_CREAT|O_TRUNC
. Si rien n'est écrit, il reste à la longueur zéro.
Assembler ces deux éléments :> file
est un idiome assez courant pour tronquer des fichiers. La plupart des gens essaient cependant de rendre cela moins étrange en écrivant : >file
.
Comme vous avez demandé dans un commentaire sur la deuxième ligne, je vais transformer mes commentaires en réponse. (même si vous ne l'avez pas demandé dans votre question.)
La deuxième ligne est une boucle qui lit les lignes otherfile
dans certaines variables nommées. Le corps de la boucle les utilise echo
pour les imprimer avec des ;
séparateurs au lieu des espaces qu’ils avaient auparavant. file
est fermé et rouvert (pour ajouter) chaque itération, car la redirection est à l'intérieur de la boucle. L'utilisation while ...;do read -r ...;done <otherfile >file
serait moins efficace, et éviterait de tronquer le fichier en premier. read -r
ne mange pas \
comme un personnage d'évasion.
Le traitement du texte à bash est assez lent. Une partie de cela est inévitable: read
doit aller un octet à la fois (un read(2)
appel système par octet) pour éviter de dépasser la fin d'une ligne. Il serait préférable d'utiliser le bon outil pour le travail:
awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile >file
--
signifie que votre script ne casse pas si otherfile
on lui donne un nom idiot --version
.
Définir le séparateur de champ de sortie sur ;
signifie que vous pouvez simplement transmettre plusieurs champs en tant qu'arguments à imprimer. Shell read
attribue le reste de la ligne avec les espaces à la dernière variable, mais il n’ya aucun moyen de dire à awk de se scinder uniquement en 5. Si cela est important, continuez simplement à utiliser une boucle bash, car c’est gênant dans awk. Perl facilite cela, car il split
peut prendre beaucoup d'arguments, mais il est beaucoup plus lent à démarrer que awk.
En fait, ce n’était pas si difficile, c’était juste une regex laide à écrire. Pour obtenir le reste de la ligne au lieu d' $5
awk, le bouclage sur les champs perd leur espace d'origine. Ma première idée viable est d'utiliser gensub
sur $0
(toute la ligne) pour supprimer les 4 premiers champs (c'est-à-dire les non-espaces suivis par des espaces), en laissant tout le reste:
awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
J'ai eu raison dès le premier essai, mais le fait d'être impressionné par moi en dit long sur la lisibilité de ce code awk. >. <
Notez comme c'est le même print
qu'auparavant, mais tail
à la place de $5
.
echo 'A B c DD e f g f' |
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
Ce serait plus impressionnant si je pouvais copier / coller le littéral et montrer que cela venait dans la sortie. Tapez un en bash avec ^ Q. ctrl-Q signifie Citer la touche suivante en tant que caractère littéral, car l'édition des lignes de style emacs de bash est identique à celle d'emacs.
http://mywiki.wooledge.org/BashFAQ contient des informations utiles sur les scripts d'une manière qui ne casse pas les données ou les noms de fichiers que vous envoyez au script.
:>
n'est pas un seul opérateur. Il sera peut-être plus facile de comprendre si vous le lisez tel quel: > file
.