3

次の例では、並べ替える必要がある 3 つの要素があります。

  1. 「[aaa]」とその下の 4 行 (常に 4 行) が 1 つのユニットを形成します。
  2. 「[kkk]」とその下の 4 行 (常に 4 行) が 1 つのユニットを形成します。
  3. "[zzz]" とその下の 4 行 (常に 4 行) が 1 つのユニットを形成します。

このパターンに従う行のグループのみをソートする必要があります。「[aaa]」の前と「[zzz]」の 4 行目以降はそのままにしておく必要があります。

から:

This sentence and everything above it should not be sorted.

[zzz]
some
random
text
here
[aaa]
bla
blo
blu
bli
[kkk]
1
44
2
88

And neither should this one and everything below it.

に:

This sentence and everything above it should not be sorted.

[aaa]
bla
blo
blu
bli
[kkk]
1
44
2
88
[zzz]
some
random
text
here

And neither should this one and everything below it.
4

3 に答える 3

1

他の行に a が含まれていないと仮定すると、次の[ようになります。

header=`grep -n 'This sentence and everything above it should not be sorted.' sortme.txt | cut -d: -f1`
footer=`grep -n 'And neither should this one and everything below it.' sortme.txt | cut -d: -f1`

head -n $header sortme.txt #print header

head -n $(( footer - 1 )) sortme.txt | tail -n +$(( header + 1 )) | tr '\n[' '[\n' | sort | tr '\n[' '[\n' | grep -v '^\[$' #sort lines between header & footer
#cat sortme.txt | head -n $(( footer - 1 )) | tail -n +$(( header + 1 )) | tr '\n[' '[\n' | sort | tr '\n[' '[\n' | grep -v '^\[$' #sort lines between header & footer

tail -n +$footer sortme.txt #print footer

目的を果たします。

メインのソート作業は 4 番目のコマンドのみで行われることに注意してください。他の行は、ヘッダーとフッターを予約します。

また、ヘッダーと最初の「[セクション]」の間に他の行はないと仮定しています。

于 2012-11-23T05:13:42.077 に答える
1

たぶん最速ではないかもしれません:) [1]しかし、それはあなたが望むことをするでしょう、私は信じています:

for line in $(grep -n '^\[.*\]$' sections.txt |
              sort -k2 -t: |
              cut -f1 -d:); do
  tail -n +$line sections.txt | head -n 5
done

これはより良いものです:

for pos in $(grep -b '^\[.*\]$' sections.txt |
             sort -k2 -t: |
             cut -f1 -d:); do
  tail -c +$((pos+1)) sections.txt | head -n 5
done

[1] 最初のものは、各セクションのセクションまでずっと読み取る必要があるため、ファイルの行数で O(N^2) のようなものです。2 つ目は、すぐに正しい文字位置をシークできるため、O(N log N) に近いはずです。

[2] これにより、各セクションには常に正確に 5 行 (ヘッダーとそれに続く 4 行) が存在することになりhead -n 5ます。ただし、それが必要になった場合に備えて、「[」で始まる次の行まで読み取るが、次の行を含まないものに置き換えるのは非常に簡単です。


開始と終了を保持するには、もう少し作業が必要です。

# Find all the sections
mapfile indices < <(grep -b '^\[.*\]$' sections.txt)
# Output the prefix
head -c+${indices[0]%%:*} sections.txt
# Output sections, as above
for pos in $(printf %s "${indices[@]}" |
             sort -k2 -t: |
             cut -f1 -d:); do
  tail -c +$((pos+1)) sections.txt | head -n 5
done
# Output the suffix
tail -c+$((1+${indices[-1]%%:*})) sections.txt | tail -n+6

それから関数を作成するか、スクリプト ファイルを作成して、sections.txt を全体で $1 に変更することをお勧めします。

于 2012-11-23T01:13:13.927 に答える