【问题标题】:How to do a circular shift of strings in bash?如何在bash中进行字符串的循环移位?
【发布时间】:2011-02-04 10:03:14
【问题描述】:

我有一个家庭作业,我需要从文件中获取输入并不断删除一行中的第一个单词并将其附加到行尾,直到完成所有组合。

我真的不知道从哪里开始,并且会感谢任何方向。

让我感到困惑的是,这应该是在不使用数组的情况下执行的。我不是在找人帮我解决问题,我只是在寻找方向。

样本输入:

Pipes and Filters
Java Swing
Software Requirements Analysis

样本输出:

Analysis Software Requirements
Filters Pipes and
Java Swing
Pipes and Filters
Requirements Analysis Software
Software Requirements Analysis
Swing Java

【问题讨论】:

标签: bash shell text-parsing


【解决方案1】:

一些应该有所帮助的花絮:当您使用字符串调用函数时,字符串被拆分为多个参数(positional parameters,命名为 $<i>n</i>,其中 n 是从1) 关于变量$IFS 中的字符(默认为空格、制表符和换行符)

function first() {
    echo $1
}
first one two three
# outputs: "one"

$* and $@ 按顺序为您提供所有位置参数。

其次,特殊变量$# 保存函数的参数个数。

第三,shift 丢弃第一个位置参数并将所有其他位置参数上移一个。

function tail() {
    shift
    echo $*
}

第四,可以使用`...` or $(...)捕获命令和函数的输出

rest=`tail $*`

第五,您可以使用pipe character (|) 将一个命令的输出发送到另一个命令的输入:

seq 5 | sort

【讨论】:

  • 这很有帮助。我现在已经弄清楚了大部分作业,只需要弄清楚如何存储所有这些字符串以便按字母顺序对它们进行排序。
  • 非常感谢 outis,非常感谢您的帮助。我喜欢你的 tail() 函数的简单性。
  • @Kyle:ghostdog74(使用前缀和后缀去除)更简单。
  • @Kyle:请注意,所有链接都指向 bash 手册,也可以在命令行中键入 man bash 获得。熟悉它;这是回答有关 bash 的问题的绝佳资源。
【解决方案2】:

要开始使用,请查看 read 内置函数:

while read first_word rest_of_the_line; do
    ... your code here ...
done

您还需要一种将输入文件输入该循环的方法。

【讨论】:

  • 非常感谢,感谢您的帮助。
【解决方案3】:

允许我向您展示一个基于@outis answer 的快速工作示例:

strings="string1 string2 string3"
next() { echo $1; }
rest() { shift; echo $*; }
for i in $strings; do
  echo $(next $strings)
  strings=$(rest $strings)
done

如果您有兴趣按顺序遍历,或者其他方式:

strings="string1 string2 string3"
next() { echo $1; }
rest() { shift; echo $*; }
totalWords=$(c() { echo $#; }; c $strings)
for i in `seq -w 1 $totalWords`; do
  echo $i: $(next $strings)
  strings=$(rest $strings)
done

【讨论】:

  • 喜欢 next() 和 rest() 函数的简单性; +1
【解决方案4】:

这是一个简短的演示。遍历单词,得到最后一个单词并放在字符串的前面。直到最后的字符串和原来的一样。

    #!/bin/bash    
    s="Software Requirements Analysis"
    org="$s"
    while true
    do
       last=${s##* } #Analysis
       front=${s% *} #Software Requirements
       s="$last $front"
       echo $s
       case "$s" in
         "$org") break;;
       esac
    done

您应该能够使用文件来完成其余的工作。

【讨论】:

  • 如果我希望它删除第一个单词并将其附加到末尾,我将对以下两行进行哪些更改? last=${s##* } #Analysis front=${s% } #Software Requirements 我不明白 s## 和 s% * 是什么意思。非常感谢您的回答,也很有帮助。
  • 评论中我的行间距不正确,很抱歉它太乱了。
  • 参见此处:en.tldp.org/LDP/abs/html/string-manipulation.html 下的 substring removal 示例。您应该能够了解它的工作原理并自己做必要的事情。
【解决方案5】:

Bash 允许您使用子字符串表示法来处理位置参数。

$ foo() { for ((i=1; i<=$#; i++)) { printf '%s ' "${@:$i}" "${@:1:$((i-1))}"; echo; }; }
$ foo one two three
one two three
two three one
three one two

然后,处理多行输入就像while 循环一样简单:

$ while read -a a; do foo "${a[@]}"; done < input.txt
Pipes and Filters
and Filters Pipes
Filters Pipes and
Java Swing
Swing Java
Software Requirements Analysis
Requirements Analysis Software
Analysis Software Requirements

或者,如果您喜欢冒险,甚至:

$ while read; do foo $REPLY; done < input.txt

我没有看到关于您的示例输出应该如何按该顺序获得的任何解释,因此此解决方案忽略了您问题的这一方面。

请注意,这并不处理所有排列/组合,只处理您在问题中指定的那些。

【讨论】:

    【解决方案6】:

    以下是如何循环左移字符串中的字符以及如何循环左移一行中的单词。

    #!/bin/bash
    
    
    # To left circular shift a string by chars
    #
    buf='12345'
    bufsize=5
    
    echo buf="$buf"
    echo bufsize=$bufsize
    
    for i in $(seq 10) c d e f; do
        buf=${buf:1:$bufsize}${buf:0:1}
        echo $buf
    done
    
    echo '--------------------------------------'
    # to left circular shift a string by words
    buf='one two three four "big bug"'
    function lcs()
    {
        s=$1
        shift
        echo $@ $s
    }
    for i in $(seq 10) c d e f; do
        buf=$(lcs $buf)
        echo $buf
    done
    

    输出

    $ ./test
    buf=12345
    bufsize=5
    23451
    34512
    45123
    51234
    12345
    23451
    34512
    45123
    51234
    12345
    23451
    34512
    45123
    51234
    --------------------------------------
    two three four "big bug" one
    three four "big bug" one two
    four "big bug" one two three
    "big bug" one two three four
    bug" one two three four "big
    one two three four "big bug"
    two three four "big bug" one
    three four "big bug" one two
    four "big bug" one two three
    "big bug" one two three four
    bug" one two three four "big
    one two three four "big bug"
    two three four "big bug" one
    three four "big bug" one two
    

    【讨论】:

      【解决方案7】:

      参数扩展可以让你分割变量的一部分。

      【讨论】:

        猜你喜欢
        • 2013-03-25
        • 2018-12-15
        • 2013-09-11
        • 2021-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-26
        相关资源
        最近更新 更多