简体   繁体   中英

Reverse the words but keep the order Bash

I have a file with lines. I want to reverse the words, but keep them in same order. For example: "Test this word" Result: "tseT siht drow"

I'm using MAC, so awk doesn't seem to work. What I got for now

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

Here is a solution that completely avoids 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"

如果xargs在Mac上可以使用:

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

Using rev and awk

Consider this as the sample input file:

$ cat file
Test this word
Keep the order

Try:

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

(This uses awk but, because it uses no advanced awk features, it should work on MacOS.)

Using in a script

If you need to put the above in a script, then create a file like:

$ 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}'

And, run the file:

$ bash script
tseT siht drow
peeK eht redro

Using 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

Applying the above to our same test 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 

Inside your read loop, you can just iterate over the words of your string and pass them to rev

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

output

tseT siht drow

You are actually in fairly good shape with bash. You can use string-indexes and string-length and C-style for loops to loop over the characters in each word building a reversed string to output. You can control formatting in a number of ways to handle spaces between words, but a simple flag first=1 is about as easy as anything else. You can do the following with your read,

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

Example Input

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

Example Use/Output

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

Look things over and let me know if you have questions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM