7

現在、コマンドからの数値のソートされた出力があります。

18,19,62,161,162,163,165

これらの番号リストを単一の番号または番号の範囲のリストに凝縮したいと思います

18-19,62,161-163,165

bashで配列を並べ替えて、次の数値を読み取って+1かどうかを確認することを考えました...基本的に同じことを行うPHP関数がありますが、Bashに置き換えるのに問題があります。

foreach ($missing as $key => $tag) {
    $next = $missing[$key+1];
    if (!isset($first)) {
        $first = $tag;
    }
    if($next != $tag + 1) {
        if($first == $tag) {
            echo '<tr><td>'.$tag.'</td></tr>';
        } else {
            echo '<tr><td>'.$first.'-'.$tag.'</td></tr>';
        }
        unset($first);
    }
}

おそらくこれを行うことができるbashのワンライナーがあると思いますが、私のグーグルは不足しています...。

更新: @Karoly Horvathに、プロジェクトを完了するために使用した簡単な回答をありがとう。私はそこにあるもっと簡単な解決策にきっと興味があるでしょう。

4

2 に答える 2

6

はい、シェルは変数置換を行います。prev設定されていない場合、その行は次のようになります。

if [ -ne $n+1] 

動作するバージョンは次のとおりです。

numbers="18,19,62,161,162,163,165"

echo $numbers, | sed "s/,/\n/g" | while read num; do
    if [[ -z $first ]]; then
        first=$num; last=$num; continue;
    fi
    if [[ num -ne $((last + 1)) ]]; then
        if [[ first -eq last ]]; then echo $first; else echo $first-$last; fi
        first=$num; last=$num
    else
        : $((last++))
    fi
done | paste -sd ","

18-19,62,161-163,165
于 2012-12-04T18:06:34.810 に答える
0

bashの関数でのみ:

#!/bin/bash

list2range() {
  set -- ${@//,/ }       # convert string to parameters

  local first a b string IFS
  local -a array
  local endofrange=0

  while [[ $# -ge 1 ]]; do  
    a=$1; shift; b=$1

    if [[ $a+1 -eq $b ]]; then
      if [[ $endofrange -eq 0 ]]; then
        first=$a
        endofrange=1
      fi
    else
      if [[ $endofrange -eq 1 ]]; then
        array+=($first-$a)
      else
        array+=($a)
      fi
      endofrange=0
    fi
  done

  IFS=","; echo "${array[*]}"
}

list2range 18,19,62,161,162,163,165

出力:

18-19,62,161-163,165
于 2019-09-20T20:11:51.477 に答える