2

From the line:

word1 word2 word3 word4 word5 word6

How to return the following:

word1
word2
word3
word4
word5
word6
word1 word2
word2 word3
word3 word4
word4 word5
word5 word6
word1 word2 word3
word2 word3 word4
word3 word4 word5
word4 word5 word6
word1 word2 word3 word4
word2 word3 word4 word5
word3 word4 word5 word6
word1 word2 word3 word4 word5
word2 word3 word4 word5 word6
word1 word2 word3 word4 word5 word6

Because limited knowledge, I used to do this one by one but if the line contains a lot of words I have to type hundred of lines. So please help me.

user163125
  • 35
  • 5
  • use `python` for such case – RomanPerekhrest Apr 13 '17 at 06:16
  • You need to look at a *permutation of words in a string* in *canonical sort order*. (**note:** not permutations of characters in a word). There are many examples to be found. (if you want it fast, use C, bash isn't entirely suited for this circumstance -- it will work, it just won't be the most efficient) – David C. Rankin Apr 13 '17 at 06:16
  • I use the script in android in terminal emulator. So probably no phyton or C or other scripting languages. – user163125 Apr 13 '17 at 06:23
  • But any how to do it in phyton/C anyway? Any help is appreciated. – user163125 Apr 13 '17 at 06:29
  • it is possible in bash as well... 1) [space delimited line to array](https://stackoverflow.com/questions/9293887/in-bash-how-do-i-convert-a-space-delimited-string-into-an-array) 2) [know how to iterate over array using index](https://stackoverflow.com/documentation/bash/471/arrays/7494/looping-through-an-array#t=201704130707326568069) 3) figure out nested loop logic to get given desired output 4) [use array slicing](https://stackoverflow.com/questions/1335815/how-to-slice-an-array-in-bash) – Sundeep Apr 13 '17 at 07:10
  • This is not a permuation. 1/3, 1/4, 1/5,1/6 are missing and many more too. – ceving Apr 13 '17 at 07:34
  • @ceving I forgot to type all the intended output. Edited – user163125 Apr 13 '17 at 10:52

3 Answers3

3

You are asking for »all substrings of a given string, without splitting words« or »all sub-arrays of an array«.

bash solution

#! /bin/bash

array=(word1 word2 word3 word4 word5 word6)

for (( length=1; length <= "${#array[@]}"; ++length )); do
    for (( start=0; start + length <= "${#array[@]}"; ++start )); do
        echo "${array[@]:start:length}"
    done
done

sh solution

Removed due to mklement0's better sh-solution.

Community
  • 1
  • 1
Socowi
  • 17,678
  • 2
  • 21
  • 39
1

Socowi's helpful answer offers an elegant bash solution[1].

To complement it with a a portable, efficient sh implementation that can also handle a variable number of spaces (and/or tabs) between the input words:

#!/bin/sh

# Input string.
string='word1 word2 word3 word4 word5 word6'

# Compress runs of multiple spaces (and/or tabs) between words, if any,
# to a single space.
string=$(printf '%s\n' "$string" | tr -s '[:blank:]' ' ')

# Count the number of words in the string.
# Note: On BSD/macOS, the result will have leading whitespace,
#       but with operators such as `-le` inside `[ ... ]` and with
#       *unquoted* references inside $(( ... )) that is not a problem.
wordCount=$(printf '%s\n' "$string" | wc -w)

start=1
while [ $start -le $wordCount ]; do
  end=$start
  while [ $end -le $wordCount ]; do
    printf '%s\n' "$string" | cut -d ' ' -f "$start-$end"
    end=$(( end + 1 ))
  done
  start=$(( start + 1 ))
done

[1] In bash, splitting a string into the elements of an array with literals is safe, as long as you apply quoting to the the elements as needed: Thus array=( word1 word2 word3 word4 word5 word6 ) works robustly (the elements don't need quoting), but array=( $str ) is not generally robust, because what $str expands to is subject to globbing (and word-splitting, which, however, is desired here). The safe way to read the whitespace-separated tokens of a single-line string into an array is: read -ra array <<<"$str"

Community
  • 1
  • 1
mklement0
  • 245,023
  • 45
  • 419
  • 492
0

I have no idea what kind of mutation you need, because what you have shown is not a permutation. But if you need a permutation you can use shell expansion:

echo {1..6}{1..6}{1..6}{1..6}{1..6}{1..6}

I have omitted the "word" strings and new-lines.

Use {word1,word2,word3,word4,word5,word6} for words.

ceving
  • 16,775
  • 7
  • 82
  • 137
  • 1
    Or `echo word{1..6}" "..." "word{1..6}$'\n'`. But even then this would only generate all permutations, most of which do not preserve the original order. – Socowi Apr 13 '17 at 09:05