Geditまたはコマンドラインを使用して、テキストファイルの4行ごとに変更することはできますか?


11

テキストファイルをタブ区切りのスプレッドシートに変換しようとしています。私のテキストファイルは次のようなものです。

Dog
Cat
Fish
Lizard
Wolf
Lion
Shark
Gecko
Coyote
Puma
Eel
Iguana

GeditまたはLibreOfficeの標準の検索および置換機能を使用すると、行末をタブに簡単に置き換えることができます。しかし、タブのキャリッジリターンを交換するだけで、次のようになります。

Dog   Cat   Fish   Lizard   Wolf   Lion   Shark   Gecko   Coyote   Puma   Eel   Iguana

しかし、私がする必要があるのは、次のようにすることです:

Dog   Cat   Fish   Lizard
Wolf   Lion   Shark   Gecko  
Coyote   Puma   Eel   Iguana

だから、4行ごとを除いて、タブの行末文字をすべて交換できますか?

GeditやLibreOfficeのようなプログラム内の正規表現を使用して、そのような条件付き反復を実行できるかどうかはわかりません。始めるのに最適なツールが何であるかさえ明確ではありません。


更新:

次のコマンドを試しました。

sed 'N;N;N;s/\n/\t/g' file > file.tsv

paste - - - - < file > file.tsv

pr -aT -s$'\t' -4 file > file.tsv

xargs -d '\n' -n4 < inputfile.txt

しかし、結果のtsvファイルをLibreOfficeで開こうとすると、列が正しくありません。これが上記のコマンドを正しく実行していないことを意味するのか、LibreOfficeインポート機能で何か間違っているのかどうかはわかりません:

CalcでのTSVオープニング

参考までに、望ましい結果は次のようになります。

適切な列

回答:


16

次のようなコマンドラインエディタを使用できます。sed

sed 'N;N;N;s/\n/\t/g' file > file.tsv

または、よりプログラム的に、GNU sedのアドレス演算子を使用して、結合したい各行にバックスラッシュ行継続文字を追加n skip mし、それに続く古典的なワンライナーで継続行を結合します。

sed '0~4! s/$/\t\\/' file | sed -e :a -e '/\\$/N; s/\\\n//; ta'

たとえば、Sed One-Liners Explainedを参照してください。

  1. バックスラッシュ「\」で終わる場合は、次の行を追加します。

    sed -e :a -e '/\\$/N; s/\\\n//; ta'
    

ただし、他の標準のテキスト処理ユーティリティのいずれかを使用すると、IMHOの方が簡単になります。

paste - - - - < file > file.tsv

(の数は-列の数に対応します)または

pr -aT -s$'\t' -4 file > file.tsv

-s$'\t出力を複数のタブで区切ってもかまわない場合は、省略できます)。


元のファイルにはWindowsスタイルのCRLF行末があるため、観察している奇妙な再インポート動作はほぼ確実です。Windowsのファイルを使用する必要がある場合は、さまざまな方法でコマンドへの変換をロールできます。

tr -d '\r' < file.csv | paste - - - -

または

sed 'N;N;N;s/\r\n/\t/g' file.csv

前者はすべてのキャリッジリターンを削除しますが、後者は各新しい行の末尾にCRを保持します(目的のエンドユーザーがWindowsを使用している場合に必要な場合があります)。


1
Windowsスタイルの行末に関する注意:それらとUnixスタイルの間で変換する標準ツールはdos2unixおよびunix2dosです。
デビッドフォースター

13

xargs常に1つのスペースで区切られた4行を1つにグループ化するために使用できます。

xargs -d '\n' -n4 < inputfile.txt

-d '\n'入力区切り文字を改行文字に設定します。そうしないと、スペースで区切られます。とにかく入力行ごとに1つの単語しかない場合は、これを省略することもできます。
-n4引数番号(出力行ごとの入力項目の数)を4に設定します。

出力:

Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana

または、スペースではなくセパレーターとしてタブを使用する場合は、後でタブを置き換えることができます。ただし、入力行にスペースが含まれている場合、それらも置換されます。

xargs -d '\n' -n4 | tr ' ' '\t'

出力(ブラウザ/端末のタブ幅に応じて表示):

Dog Cat Fish    Lizard
Wolf    Lion    Shark   Gecko
Coyote  Puma    Eel Iguana

この方法には、入力行の総数が4の倍数でない場合でも、適切に動作するという利点があります。
エリアケイガン

3

以下も使用できます。

awk -v ORS="" '{print $1; print NR%4==0?"\n":"\t"}' file > file.tsv 

2つのawk組み込み変数は次のとおりです。

  • ORSO utput R ECORD S eparator(デフォルト=改行)。各印刷コマンドの最後に追加されます。
  • NRNの現在のアンバーR OW AWKは、処理されます。

このコマンドは、各行について、最初の(そしてここだけの)列の内容を表示します。次に、除算の残りのNR4をテストして、改行またはタブを追加することを選択します。


3

別の最短awkアプローチ:

awk '{printf $0 (NR%4?"\t":"\n")}' infile

このprintf関数は、 1つの列のみが次と次と...そしてタブに続いて\t、それぞれの後の文字はなくなりますprintfの\nときewline文字をN個のアンバーRの ECORDが要因だった4NR%4返されます0何三項演算子である(偽の)condition(s)?when-true:when-falseやっています。)


3

これに対する私の解決策はsed、との組み合わせを使用することですsed。まず、次の>ソリューションを使用して、4行ごとに特殊文字でマークを付けることができます。

この場合、5行目から開始し、その後4行ごとにマークを付けます。GNU sedでは、アドレスとして指定できます5~4。次のコマンドを使用できます。

sed '5~4s/^/>/' file1 > file2

次に、sedループを使用して行うことができる改行を削除する必要があります。

sed ':a;N;s/\n/ /;ba' file2 > file3

以下のように、改行を他の文字に変換する簡単な方法がありますtr

tr '\n' ' ' < file2 > file3

どちらにしても、2つを組み合わせると

Dog   Cat   Fish   Lizard   >Wolf   Lion   Shark   Gecko   >Coyote   Puma   Eel   Iguana

sedバージョンは末尾の改行を残しますが、trバージョンはそうしません)

その後、挿入する特殊文字を改行に変換するだけです。たとえば、改行で区切るためにタブ区切りファイルを変換するをご覧ください。この場合、>改行に変更します。

sed 'y/>/\n/' file3 > outfile

このyコマンドは、tr1つの文字を別の文字に変換するのと同じ機能を実行しますが、sここでも同じように使用できます。ではsg行(sed 's/>/\n/g')の各一致を操作する必要があります。

2つの中間ファイルを作成する代わりに、パイプを使用できます。

$ sed '5~4s/^/>/' file | sed ':a;N;s/\n/ /;ba' | sed 'y/>/\n/'
Dog Cat Fish Lizard 
Wolf Lion Shark Gecko 
Coyote Puma Eel Iguana

末尾のスペースが問題になる場合は、別のコマンドを追加して削除できます。

| sed 's/ $//'

2

「完全性」ために、純粋なbashソリューションを示します。

#!/usr/bin/env bash

sep=$'\t'

while read one \
      && read two \
      && read three \
      && read four
do
  printf "%s\n" "$one$sep$two$sep$three$sep$four"
done

IFS適切に設定されていると仮定すると、スペースでも機能します(デフォルトではAFAIKである必要があります)。さらに、これは移植可能なシェルスクリプトであり、POSIX互換のシェルで動作する可能性があると思います


1
これは$' '、引用の形式がPOSIXで必要とされないため、一般にPOSIX互換シェルに移植できません。たとえば、dashshUbuntuでデフォルトで提供される)では、printf '%s\n' $'a\tb'単にoutputsを実行します$a\tb。ただし、これが役に立たないというわけではありません。bashで動作します。ただし、他のいくつかのソリューションと同様に、入力の行数が4の倍数でない場合、不完全な出力が生成されます。また、read -rここでは入力ファイル内のバックスラッシュエスケープの拡張が望ましいと考える理由がないため、の使用をお勧めします。
エリアケイガン

単純にできるprintf '%s\t%s\t%s\t%s\n' "$one" "$two" "$three" "$four"
18

2

vimマクロ(qで記録)が操作を適用し、3行スキップする可能性があります。次に、そのマクロをn回実行するだけです。

例えば:

qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q

2

Geditソリューションを要求したので、次のようなものが機能するはずです。

見つける:

(\w+)[\r\n]+(\w+)[\r\n]+(\w+)[\r\n]+(\w+)[\r\n]+

と置換する:

\1\t\2\t\3\t\4\n

正規表現のチェックボックスがマークされていることを確認してください。

使い方:

最初のステップは、\ w +を使用して一連の単語文字を検索し、式を括弧で囲むことにより変数\ 1の結果をキャプチャすることです。

(\w+)

次に、一連の行末文字、\ rと\ n、またはCRとLFを検索します。Windows形式のファイルは両方を使用するため、これらの2つの文字を角括弧で囲むことで文字クラスを作成します。プラス記号は、1つ以上の文字を検索します。

[\r\n]+

最後に、これをさらに3回繰り返し、後続の各単語を変数\ 2、\ 3、および\ 4に格納します。これにより、式による置換が簡単になります。必要な書式設定に適した場所に、タブ文字\ tと改行文字\ nを配置するだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.