【问题标题】:Reverse the words but keep the order Bash颠倒单词但保持顺序 Bash
【发布时间】:2018-05-22 01:03:43
【问题描述】:

我有一个带行的文件。我想颠倒单词,但保持它们的顺序相同。 例如:“测试这个词” 结果:“tseT siht drow”

我使用的是 MAC,所以 awk 似乎不起作用。 我现在得到了什么

input=FILE_PATH
while IFS= read -r line || [[ -n $line ]]
do
    echo $line | rev
done < "$input"

【问题讨论】:

    标签: bash macos shell terminal


    【解决方案1】:

    这里有一个完全避免awk的解决方案

    #!/bin/bash
    
    input=./data
    while read -r line ; do
        for word in  $line ; do
            output=`echo $word | rev`
            printf "%s " $output
        done
        printf "\n"
    done < "$input"
    

    【讨论】:

    • 这行得通!已添加 || [[ -n $line ]] ,所以它也会读取最后一行。
    【解决方案2】:

    如果 xargs 在 mac 上工作:

    echo "Test this word"  | xargs -n 1 | rev | xargs
    

    【讨论】:

      【解决方案3】:

      在您的读取循环中,您可以遍历字符串中的单词并将它们传递给rev

      line="Test this word"
      for word in "$line"; do
          echo -n " $word" | rev
      done
      echo  # Add final newline
      

      输出

      tseT siht drow
      

      【讨论】:

        【解决方案4】:

        实际上,您使用 bash 的状态相当不错。您可以使用 string-indexesstring-length 以及 C 风格的 for 循环来遍历每个单词中的字符,从而构建一个要输出的反转字符串。您可以通过多种方式控制格式以处理单词之间的空格,但是一个简单的标志first=1 与其他任何东西一样简单。您可以通过阅读执行以下操作,

        #!/bin/bash
        
        while read -r line || [[ -n $line ]]; do        ## read line
            first=1                                     ## flag to control space
            a=( $( echo $line ) )                       ## put line in array
            for i in "${a[@]}"; do                      ## for each word
                tmp=                                    ## clear temp
                len=${#i}                               ## get length
                for ((j = 0; j < len; j++)); do         ## loop length times
                    tmp="${tmp}${i:$((len-j-1)):1}"     ## add char len - j to tmp
                done
                if [ "$first" -eq '1' ]; then           ## if first word
                    printf "$tmp"; first=0;             ## output w/o space
                else
                    printf " $tmp"                      ## output w/space
                fi
            done
            echo ""     ## output newline
        done
        

        示例输入

        $ cat dat/lines2rev.txt
        my dog has fleas
        the cat has none
        

        使用/输出示例

        $ bash revlines.sh <dat/lines2rev.txt
        ym god sah saelf
        eht tac sah enon
        

        检查一下,如果您有任何问题,请告诉我。

        【讨论】:

          【解决方案5】:

          使用 rev 和 awk

          将此视为示例输入文件:

          $ cat file
          Test this word
          Keep the order
          

          试试:

          $ rev <file | awk '{for (i=NF; i>=2; i--) printf "%s%s",$i,OFS; print $1}'
          tseT siht drow
          peeK eht redro
          

          (这使用了 awk,但是因为它没有使用高级的 awk 功能,所以它应该可以在 MacOS 上运行。)

          在脚本中使用

          如果您需要将上述内容放入脚本中,请创建一个类似的文件:

          $ cat script
          #!/bin/bash
          input="/Users/Anastasiia/Desktop/Tasks/test.txt"
          rev <"$input" | awk '{for (i=NF; i>=2; i--) printf "%s%s",$i,OFS; print $1}'
          

          然后,运行文件:

          $ bash script
          tseT siht drow
          peeK eht redro
          

          使用 bash

          while read -a arr
          do
             x=" "
             for ((i=0; i<${#arr}; i++))
             do
                ((i == ${#arr}-1)) && x=$'\n'
                printf "%s%s" $(rev <<<"${arr[i]}") "$x"
             done
          done <file
          

          将以上内容应用到我们的同一个测试文件中:

          $ while read -a arr; do x=" "; for ((i=0; i<${#arr}; i++)); do ((i == ${#arr}-1)) && x=$'\n'; printf "%s%s" $(rev <<<"${arr[i]}") "$x"; done; done <file
          tseT siht drow 
          peeK eht redro 
          

          【讨论】:

          • @SAllexandriya 我刚刚添加了一个示例,展示了如何将代码放入脚本并执行脚本。