テキストファイルの1行を1行上下に移動するには?

テキストファイルの1行を1行上下に移動するには?

テキストファイルがいくつかありますが、次のことをしたいと思います。移動するファイルの前または次の行のすべての行(ファイルの開始行または終了行は元の場所に残ります)。私は動作するコードがいくつかありますが、汚れて見え、すべての極端なケースに対処したとは思いません。したがって、これをよりよく実行できるツールやパラダイムがあるかどうか疑問に思います(例:わかりやすくする)コード(6ヶ月以内の他の読者や私にとって)、デバッグが簡単でメンテナンスが簡単実際には重要ではありません。

move_up() {
  # fetch line with head -<line number> | tail -1
  # insert that one line higher
  # delete the old line
  sed -i -e "$((line_number-1))i$(head -$line_number $file | tail -1)" -e "${line_number}d" "$file"
}

move_down() {
  file_length=$(wc -l < "$file")
  if [[ "$line_number" -ge $((file_length - 1)) ]]; then
    # sed can't insert past the end of the file, so append the line
    # then delete the old line
    echo $(head -$line_number "$file" | tail -1) >> "$file"
    sed -i "${line_number}d" "$file"
  else
    # get the line, and insert it after the next line, and delete the original
    sed -i -e "$((line_number+2))i$(head -$line_number $file | tail -1)" -e "${line_number}d" "$file"
  fi
}

これらの関数の内側または外側の入力に対してエラーチェックを実行できますが、誤った入力(整数以外のファイル、ファイルの長さよりも大きい行番号など)が正しく処理されると、ボーナスポイントになります。

最新のDebian / UbuntuシステムのBashスクリプトで実行したいと思います。常にrootアクセス権を持っているわけではありませんが、「標準」ツール(共有ネットワークサーバーなど)をインストールすると期待できます。可能要求の正当性を証明できる場合は、追加のツールのインストールを要求できます(外部依存関係が少ないほど良いです)。

例:

$ cat b
1
2
3
4
$ file=b line_number=3 move_up
$ cat b
1
3
2
4
$ file=b line_number=3 move_down
$ cat b
1
3
4
2
$ 

答え1

〜のようにアーチャーマール提案されているように、以下を使用してスクリプトを作成できますed

printf %s\\n ${linenr}m${addr} w q | ed -s infile

つまり

linenr                      #  is the line number
m                           #  command that moves the line
addr=$(( linenr + 1 ))      #  if you move the line down
addr=$(( linenr - 2 ))      #  if you move the line up
w                           #  write changes to file
q                           #  quit editor

たとえば、行番号を移動します。21チーム:

printf %s\\n 21m19 w q | ed -s infile

行番号を211行下に移動します。

printf %s\\n 21m22 w q | ed -s infile

しかし、特定の行を1行上下に移動するだけでよいので、実際に2つの連続行を交換したいと言うこともできます。会うsed

sed -i -n 'addr{h;n;G};p' infile

つまり

addr=${linenr}           # if you move the line down
addr=$(( linenr - 1 ))   # if you move the line up
h                        # replace content of the hold  buffer with a copy of the pattern space
n                        # read a new line replacing the current line in the pattern space  
G                        # append the content of the hold buffer to the pattern space
p                        # print the entire pattern space

たとえば、行番号を移動します。21チーム:

sed -i -n '20{h;n;G};p' infile

行番号を211行下に移動します。

sed -i -n '21{h;n;G};p' infile

gnu sed上記の構文を使用しました。移植性が問題の場合:

sed -n 'addr{
h
n
G
}
p' infile

それ以外の一般的な検査は次のとおりです。ファイルが存在し、書き込み可能ですfile_length > 2line_no. > 1line_no. < file_length

答え2

viにはmoveというコマンドがありますm

テキストモードでviを使用できます:ex

  $line_number=7
  $line_up=$(($line_number + 1 ))
  (echo ${line_number}m${line_up} ; echo wq ) | ex foo

どこ

  • fooあなたのファイルです。

答え3

vimsを使う(sedモードのvim):https://github.com/MilesCranmer/vim-stream

あなたはできます:

cat file.txt | vims "$NUMBERm.-1"

行を1つ下に移動します。

関連情報