23

我有一个字符串中的单词列表:

str="SaaaaE SeeeeE SbbbbE SffffE SccccE"

我想扭转它以获得

"SccccE SffffE SbbbbE SeeeeE SaaaaE"

我怎么能做到这一点ash

4

17 回答 17

27

您可以awk按如下方式使用:

echo "$str" | awk '{ for (i=NF; i>1; i--) printf("%s ",$i); print $1; }'
于 2014-12-30T11:09:38.913 回答
21

是的,你可以试试这些命令,

对于字符串

echo "aaaa eeee bbbb ffff cccc"|tr ' ' '\n'|tac|tr '\n' ' '

对于变量

echo $str|tr ' ' '\n'|tac|tr '\n' ' '
于 2014-12-30T10:35:46.497 回答
8

你可以使用 awk:

echo "aaaa eeee bbbb ffff cccc" | awk '{for(i=NF;i>0;--i)printf "%s%s",$i,(i>1?OFS:ORS)}'

循环遍历字段,打印每个字段。OFS是输出字段分隔符(默认为空格)并且ORS是输出记录分隔符(换行符)。

我假设您不希望每个单词中的字母顺序颠倒。

于 2014-12-30T10:36:46.527 回答
6

如果您需要纯外壳,无需外部工具,请考虑:

reverse_word_order() {
    local result=
    for word in $@; do
        result="$word $result"
    done
    echo "$result" 
}

reverse_word_order "$str"

否则tac可以立即为您提供帮助:

echo -n "$str" | tac -s' '

或者

tac -s' ' <<<"$str" | xargs 
于 2016-04-29T17:28:53.747 回答
4

这是一个awkusing do while(在 Stackoverflow 上用的不多)
不需要额外的变量i

echo "aaaa eeee bbbb ffff cccc"|awk '{do printf "%s"(NF>1?FS:RS),$NF;while(--NF)}'
cccc ffff bbbb eeee aaaa
于 2014-12-30T11:11:36.403 回答
3

这适用于sh(我没有ash所以无法验证):

reverse() {
    for (( i = ${#*}; i > 0; i-- ))
    {
        echo ${!i}
    }
}

像这样使用它:

$ reversed=$(reverse foo bar baz)
$ echo $reversed
baz bar foo

这里有一些替代方案。首先,一个不使用 C 风格的for

reverse() {
    while [ ${#*} -gt 0 ]
    do
      echo ${*: -1}
      set -- "${@:1:$(($#-1))}"
    done
}

下一个(从这里开始)适用于替换不起作用的地方(例如在 Android 上)

reverse() {
    if [ "$#" -gt 0 ]; then
        local arg=$1
        shift
        reverse "$@"
        printf '%s\n' "$arg"
    fi
}

我试图找到一个适用于 Android 脚本的解决方案,sh它不喜欢 C 风格for或复杂的替换操作。我最终选择了最后一个示例,因为它两个都不使用。

于 2016-09-04T09:23:02.433 回答
2

如果使用 Haskell 是可以接受的,有一个很好的工具叫做 hawk (haskell-awk) 可以很容易地做到这一点。首先你需要安装它:

$ cabal install haskell-awk

然后:

$ echo $str | hawk -m reverse

你需要~/.cabal/bin在你PATH的找到hawk

于 2015-04-17T08:16:14.337 回答
1

sed 分组:

str="SaaaaE SeeeeE SbbbbE SffffE SccccE"

echo $str | sed 's/\(.* \)\(.* \)\(.* \)\(.* \)\(.*\)/\5 \4\3\2\1/g'
于 2016-04-29T19:22:18.087 回答
1

使用 awk 解决方案do...while在输入字符串为空时会抛出错误,而一些使用for循环的 awk 解决方案会在输入字符串为空时打印空行。这比以前的 awk 解决方案略短,--NF在 POSIX 中没有未定义行为的麻烦,并且当输入为空字符串时它不会抛出错误或打印空行:

$ echo "aaaa eeee bbbb ffff cccc" | awk '{i=NF;while(i)printf "%s",$i (i-->1?FS:RS)}'

cccc ffff bbbb eeee aaaa
于 2020-09-30T23:06:40.517 回答
0
/* 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

输出


**** 反转字符串的程序 ***


在这里输入:我爱我的印度

您已进入:我爱我的印度

字符串的反转:印度我的爱我

于 2015-04-11T20:54:32.197 回答
0

重击

这是我使用的功能,(未在灰中测试)

#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

短跑

(也适用于 bash,但有些人似乎厌恶 echo)

rwo(){ echo "$*"|tr ' ' '\n'|tac|tr '\n' ' ';}

正如 0andriy 暗示的那样,我们可以打高尔夫球,(或者如果您的平台有tac但没有tr):

rwo(){ echo "$*"|tac -s " ";} #dash compatible 
rwo(){ tac -s " "<<<"$@";} #bashism
于 2017-10-17T17:06:35.113 回答
0

这是对 GNU sed 手册中的Reverse Characters of Lines脚本的轻微改编:

#!/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

它做了一些假设,例如没有前导或尾随空格,并且所有单词都被一个空格分隔。带有前导或尾随空格的行保持不变,并且单词未全部由一个空格分隔的行在它们所在的位置留下额外的空格,这可能不是我们想要的。

该脚本应与任何符合 POSIX 的 sed 和基本正则表达式 (BRE) 一起使用。使用 GNU sed 和扩展正则表达式 (ERE) 可以提高可读性,例如

s/\n(\S+) (.*) (\S+)\n/\3 \n\2\n \1/

对于主要替换,但如果您首先使用 sed 来解决这个问题,那么可读性可能不是最关心的问题。

于 2018-07-20T15:27:51.400 回答
0

如果要从文件中读取输入(如此处询问:从文件中读取行反向),我创建了以下 bash 脚本,该脚本在不更改文件行顺序的情况下反向打印每行的单词(我需要这个,例如在说中文等中阅读单词 RTL 而不是 LTR 时:

#!/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}"


注意:
1) 确保输入文件为 UNIX EOL 格式,否则每行的最后一个单词可能会被截断
2) 为简单起见,可能省略了一些错误检查

于 2016-09-04T12:00:57.687 回答
0

另一个纯 bash 解决方案:

str='test a is this'; res=""; prev=""
while [ "$prev" != "$str" ]; do res="$res${str##* } "; prev="$str"; str="${str% *}"; done
于 2016-08-03T13:31:38.163 回答
0

For those wanting a simple one-line solution that isn't convoluted, tac is the way to go. Here is the simplest way I know using tac and command substitution:

echo $(tac -s ' ' <<< $str)
于 2021-09-16T22:42:50.293 回答
0
echo "aaaa eeee bbbb ffff cccc" | xargs echo | xargs -n1 echo | tac | xargs echo 

我几乎所有东西都使用 xargs。它可以将每个单词放在一行中-n1,但它可以将所有单词放回一行,没有它

  • 通过回显字符串取消引用它,以便下一个 xargs 将每个单词视为一个单词
  • 将每个单词回显到自己的行
  • 颠倒行的顺序
  • 再次将它们全部打印在一行上

tac可能有可以替代其中一些步骤的参数

于 2021-07-13T08:12:17.937 回答
0

反转字符串,但将 endmark 保留在适当的位置。

#!/bin/bash

#set -x

read -p "Enter a sentence: " sentence

myArray=( $sentence )

counter="${#myArray[@]}"

i=0

for word in "${myArray[@]}"
do
        if [ $counter -lt 1 ]
        then break
        fi

reverseArray[$i]="${myArray[$counter-1]}"
 
letterCounter=0
 
while read -n 1 letter
do
if [ "$letter" == '?' ] || [ "$letter" == '!' ] || [ "$letter" == '.' ]
then 
endmark="$letter"
reverseArray[$i]=$(echo "${reverseArray[$i]}" | head -c "$letterCounter")
fi
((letterCounter++))
done < <(echo "${reverseArray[$i]}")

((i++))
((counter--))
done

echo "${reverseArray[*]}$endmark"

exit

输入:你好,世界?

输出:世界你好?

于 2022-02-06T03:11:27.250 回答