问题
I have a list of words in a string:
str="SaaaaE SeeeeE SbbbbE SffffE SccccE"
I want to reverse it in order to get
"SccccE SffffE SbbbbE SeeeeE SaaaaE"
How I can do that with ash
?
回答1:
You can use awk
as follows:
echo "$str" | awk '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }'
回答2:
Yes, you can try these commands,
For string,
echo "aaaa eeee bbbb ffff cccc"|tr ' ' '\n'|tac|tr '\n' ' '
For the variable,
echo $str|tr ' ' '\n'|tac|tr '\n' ' '
回答3:
You could use awk:
echo "aaaa eeee bbbb ffff cccc" | awk '{for(i=NF;i>0;--i)printf "%s%s",$i,(i>1?OFS:ORS)}'
Loop backwards through the fields, printing each one. OFS
is the Output Field Separator (a space by default) and ORS
is the Output Record Separator (a newline).
I'm assuming that you don't want the order of the letters in each word to be reversed.
回答4:
Here is an awk
using do
while
(not much used here at Stackoverflow)
No extra variable needed i
echo "aaaa eeee bbbb ffff cccc"|awk '{do printf "%s"(NF>1?FS:RS),$NF;while(--NF)}'
cccc ffff bbbb eeee aaaa
回答5:
if you need pure shell, no external tools, consider this:
reverse_word_order() {
local result=
for word in $@; do
result="$word $result"
done
echo "$result"
}
reverse_word_order "$str"
Otherwise tac
can help you straight away:
echo -n "$str" | tac -s' '
or
tac -s' ' <<<"$str" | xargs
回答6:
If using Haskell is acceptable, there is a nice tool called hawk (haskell-awk) which can do this very easily. First you need to install it:
$ cabal install haskell-awk
Then:
$ echo $str | hawk -m reverse
You need ~/.cabal/bin
in your PATH
to find hawk
.
回答7:
sed grouping:
str="SaaaaE SeeeeE SbbbbE SffffE SccccE"
echo $str | sed 's/\(.* \)\(.* \)\(.* \)\(.* \)\(.*\)/\5 \4\3\2\1/g'
回答8:
This works in sh
(I don't have ash
so can't verify that):
reverse() {
for (( i = ${#*}; i > 0; i-- ))
{
echo ${!i}
}
}
use it like this:
$ reversed=$(reverse foo bar baz)
$ echo $reversed
baz bar foo
Here are some alternatives. First, one that doesn't use the C-style for
:
reverse() {
while [ ${#*} -gt 0 ]
do
echo ${*: -1}
set -- "${@:1:$(($#-1))}"
done
}
The next one (from here) works where substitutions don't (e.g. on Android)
reverse() {
if [ "$#" -gt 0 ]; then
local arg=$1
shift
reverse "$@"
printf '%s\n' "$arg"
fi
}
I was trying to find a solution that worked in an Android script, where sh
doesn't like C-style for
or complex substitution operations. I ended up with the last example because it uses neither.
回答9:
/* 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
OUTPUT
**** Program to Reverse a String ***
Enter Here : I love My India
You have entered : I love My India
Reverse of String : India My love I
回答10:
Another pure bash solution:
str='test a is this'; res=""; prev=""
while [ "$prev" != "$str" ]; do res="$res${str##* } "; prev="$str"; str="${str% *}"; done
回答11:
If the input is to be read from file (as asked here: read line reverse from a file), I created the following bash script that prints words of each line in reverse without changing the order of lines of the file (I needed this e.g. when reading words RTL instead of LTR in say chinese, 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}"
Notes:
1) Make sure the input file is in UNIX EOL format otherwise last word might be truncated from each line
2) Some error checks might have been omitted for sake of simplicity
回答12:
BASH
This is the function that I use, (not tested in ash)
#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
DASH
(also works in bash, but some people seem to have an aversion to echo)
rwo(){ echo "$*"|tr ' ' '\n'|tac|tr '\n' ' ';}
回答13:
This is a slight adaptation of the Reverse Characters of Lines script in the GNU sed manual:
#!/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
It makes a few assumptions such as no leading or trailing blanks and all the words being separated by exactly one space. Lines with leading or trailing blanks stay untouched, and lines where the words aren't all separated by exactly one space leave the extra spaces where they are, which might not be what is desired.
The script should work with any POSIX conformant sed and basic regular expressions (BRE). Using GNU sed and extended regular expressions (ERE) would allow for better readability, such as
s/\n(\S+) (.*) (\S+)\n/\3 \n\2\n \1/
for the main substitution, but if you're using sed for this problem in the first place, readability is probably not the top concern.
来源:https://stackoverflow.com/questions/27703776/how-to-reverse-a-list-of-words-in-a-shell-string