J'ai une liste de mots dans une chaîne:
str="SaaaaE SeeeeE SbbbbE SffffE SccccE"
Je veux inverser pour obtenir
"SccccE SffffE SbbbbE SeeeeE SaaaaE"
Comment puis-je faire cela avec ash
?
Vous pouvez utiliser awk
comme suit:
echo "$str" | awk '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }'
Oui, vous pouvez essayer ces commandes,
Pour string,
echo "aaaa eeee bbbb ffff cccc"|tr ' ' '\n'|tac|tr '\n' ' '
Pour la variable,
echo $str|tr ' ' '\n'|tac|tr '\n' ' '
Vous pouvez utiliser awk:
echo "aaaa eeee bbbb ffff cccc" | awk '{for(i=NF;i>0;--i)printf "%s%s",$i,(i>1?OFS:ORS)}'
Parcourez les champs en arrière et imprimez-les. OFS
est le séparateur de champ de sortie (un espace par défaut) et ORS
est le séparateur d'enregistrement de sortie (nouvelle ligne).
Je suppose que vous ne voulez pas que l'ordre des lettres dans chaque mot soit inversé.
Voici une awk
utilisant do
while
(peu utilisée ici à Stackoverflow)
Aucune variable supplémentaire nécessaire i
echo "aaaa eeee bbbb ffff cccc"|awk '{do printf "%s"(NF>1?FS:RS),$NF;while(--NF)}'
cccc ffff bbbb eeee aaaa
si vous avez besoin de pur Shell, sans outils externes, prenez en compte ceci:
reverse_Word_order() {
local result=
for Word in $@; do
result="$Word $result"
done
echo "$result"
}
reverse_Word_order "$str"
Sinon tac
peut vous aider tout de suite:
echo -n "$str" | tac -s' '
ou
tac -s' ' <<<"$str" | xargs
groupement sed:
str="SaaaaE SeeeeE SbbbbE SffffE SccccE"
echo $str | sed 's/\(.* \)\(.* \)\(.* \)\(.* \)\(.*\)/\5 \4\3\2\1/g'
Si utiliser Haskell est acceptable, il existe un outil de Nice appelé hawk (haskell-awk) qui peut le faire très facilement. Vous devez d'abord l'installer:
$ cabal install haskell-awk
Ensuite:
$ echo $str | hawk -m reverse
Vous avez besoin de ~/.cabal/bin
dans votre PATH
pour trouver hawk
.
Cela fonctionne dans sh
(je n'ai pas ash
alors je ne peux pas le vérifier):
reverse() {
for (( i = ${#*}; i > 0; i-- ))
{
echo ${!i}
}
}
utilisez-le comme ceci:
$ reversed=$(reverse foo bar baz)
$ echo $reversed
baz bar foo
Voici quelques alternatives. Tout d'abord, celui qui n'utilise pas le style C for
:
reverse() {
while [ ${#*} -gt 0 ]
do
echo ${*: -1}
set -- "${@:1:$(($#-1))}"
done
}
Le prochain (de ici ) fonctionne là où les substitutions ne fonctionnent pas (par exemple sur Android)
reverse() {
if [ "$#" -gt 0 ]; then
local arg=$1
shift
reverse "$@"
printf '%s\n' "$arg"
fi
}
J'essayais de trouver une solution qui fonctionnait dans un script Android, dans laquelle sh
n'aimait pas les opérations de substitution de type C for
ou complexes. J'ai fini avec le dernier exemple car il n'utilise ni l'un ni l'autre.
C’est la fonction que j’utilise, (non testée en cendre)
#reverse_Word_order
function rwo(){ tr ' ' '\n'<<<"$@"|tac|tr '\n' ' ';}
echo $(rwo 'Hello There I am You')
#based on https://stackoverflow.com/a/27703859/1153645
(fonctionne également en bash, mais certaines personnes semblent avoir une aversion pour l'écho)
rwo(){ echo "$*"|tr ' ' '\n'|tac|tr '\n' ' ';}
Une autre solution pure bash:
str='test a is this'; res=""; prev=""
while [ "$prev" != "$str" ]; do res="$res${str##* } "; prev="$str"; str="${str% *}"; done
/* Shell script to reverse the Input String */
echo " **** Program to Reverse a String **** "
read -p " Enter Here : " text
echo "You have entered : " $text
echo -n "Reverse of String : "
arr=($text)
arrlength=${#arr[@]}
arrlength=`expr $arrlength - 1`
while [ $arrlength -ge 0 ]
do
echo -n ${arr[arrlength]}
echo -n " "
arrlength=`expr $arrlength - 1`
done
echo
SORTIE
**** Programme pour inverser une chaîne ***
Entrez ici: j'aime mon Inde
Vous avez entré: J'aime mon Inde
Reverse of String: India Mon amour, je
Ceci est une légère adaptation du Caractères inversés des lignes script dans le manuel GNU sed:
#!/usr/bin/sed -f
# Skip lines without blanks
/[[:blank:]]/! b
# Embed line between newlines
s/^.*$/\
&\
/
# Reset the t flag
tx
# Label to jump to
:x
# Swap first and last Word between newlines for three or more words
s/\n\([^[:blank:]][^[:blank:]]*\) \(.*\) \([^[:blank:]][^[:blank:]]*\)\n/\3 \
\2\
\1/
# Jump to label if there was a change on the line
tx
# Swap first and last Word between newlines for exactly two words
s/\n\([^[:blank:]][^[:blank:]]*\) \([^[:blank:]][^[:blank:]]*\)\n/\2\
\
\1/
# Remove the newline markers
s/\n//g
Il fait quelques hypothèses telles que l’absence de blancs en début et en fin de texte et que tous les mots sont séparés par un seul espace. Les lignes avec des espaces en début ou en fin de ligne restent inchangées et les lignes où les mots ne sont pas séparés par un seul espace laissent les espaces supplémentaires où ils se trouvent, ce qui pourrait ne pas correspondre à ce que vous souhaitez.
Le script doit fonctionner avec toutes les expressions rationnelles BRE (BRE). L'utilisation de GNU expressions régulières sed et étendues (ERE) permettrait une meilleure lisibilité, telle que
s/\n(\S+) (.*) (\S+)\n/\3 \n\2\n \1/
pour la substitution principale, mais si vous utilisez sed pour résoudre ce problème en premier lieu, la lisibilité n'est probablement pas la principale préoccupation.
Si l'entrée doit être lue à partir d'un fichier (comme demandé ici: lire ligne inversée à partir d'un fichier ), le fichier (j'en avais besoin par exemple lors de la lecture de mots RTL au lieu de LTR en chinois, etc.):
#!/bin/bash
fileName="$1"
outputFile="ReversedFile.npp"
echo > ${outputFile}
lineCount=`cat $fileName | wc -l`
for ((lineNum=1; ${lineNum} <= ${lineCount}; lineNum++))
do
echo
echo "Processing Line ${lineNum} of ${lineCount} ..."
lineOfFile="`cat $fileName | head -${lineNum} | tail -1`"
echo "${lineOfFile}"
rm -f wordFile.txt
for eachWord in `echo "${lineOfFile}"`
do
echo "${eachWord}" >> wordFile.txt
done
if [ -e wordFile.txt ]; then
thisLine=""
wordCount=`cat wordFile.txt| wc -l`
for ((wordNum=${wordCount}; ${wordNum}>=1; wordNum--))
do
wordOfLine="`cat wordFile.txt | head -${wordNum} | tail -1`"
echo "${wordNum} of ${wordCount} is ${wordOfLine}"
thisLine+="${wordOfLine} "
done
echo "output"
echo "${thisLine}"
echo "${thisLine}" >> ${outputFile}
rm -f wordFile.txt
fi
done
echo
echo "Output in File ${outputFile}"
Remarques:
1) Assurez-vous que le fichier d'entrée est au format UNIX EOL, sinon le dernier mot pourrait être tronqué à partir de chaque ligne
2) Certaines vérifications d'erreur ont peut-être été omises pour des raisons de simplicité