複数のファイルで特定の文字が見つかるたびに行をストリーミングします。

複数のファイルで特定の文字が見つかるたびに行をストリーミングします。

以下は、1行に変換したいファイルの例です。

-
Jun 6th
something2
09:00
some text blah blah
something1
Jun 6th
something1
09:00
some text xxx
something1

この行をcsvと同じ1行にインポートしようとしています。例:

Jun 6th, something2, 09:00, some text blah blah, something1
Jun 6th, something1, 09:00, some text xxx, something1

答え1

次のSED文を試すことができます。

sed -ne '/^–/{g; /./!b; s/\n//; s/\n/, /g; p; z; h; b}; H' INPUTFILE

説明する:

/^–/{                 -->  if line starts with char "–", then:
    g                 -->      copy hold space to pattern space
    /./!b             -->      empty line? restart cycle
    s/\n//            -->      get rid of first newline
    s/\n/, /g         -->      replace all other newlines by ", "
    p                 -->      print pattern space
    z                 -->      erase pattern space
    h                 -->      erase hold space
    b                 -->      start new cycle
    }
H                     -->  otherwise, append newline + pattern space to hold space

入力する:


Jun 6th
something2
09:00
some text blah blah
some other thing2
Jun 7th
something1
10:30
some text xxx
some other thing1
Jun 9th
something3
12:15
some text yyy
some other thing3
Jun 8th
something4
07:05
some text zzz
some other thing4

出力:

Jun 6th, something2, 09:00, some text blah blah, some other thing2
Jun 7th, something1, 10:30, some text xxx, some other thing1
Jun 9th, something3, 12:15, some text yyy, some other thing3
Jun 8th, something4, 07:05, some text zzz, some other thing4

お役に立てば幸いです。

答え2

まず、データが2種類のダッシュ文字、つまりASCIIハイフンとUnicodeダッシュ(U + 2013)に分かれていることに注意することが重要です。

AwkのGNU実装(GNU Awk)は、レコードを分離するための正規表現を処理できます。これは文章です:

$ gawk -v RS='\n?[–-]\n' -v FS='\n' -v OFS=', ' '$1 = $1' data
Jun 6th, something2, 09:00, some text blah blah, something1
Jun 6th, something1, 09:00, some text xxx, something1

data例を含むファイルはそのまま保存されます。

オプションの改行文字とASCIIダッシュ、またはUnicodeダッシュと改行文字と一致するレコード区切り正規表現を設定しました。その後、これらのレコードのフィールド区切り文字は改行文字です。出力区切り文字はカンマとスペースです。

この表現は$1=$12つの目的に使用されます。フィールドを自分自身に割り当てると、カスタムフィールド区切り文字$0を考慮してレコードが再編成されます。OFSその後、印刷するだけです。データはレコード区切り文字で始まるので、最初は空のレコードがあります。このレコードの場合、式は$1 = $1空白値を割り当て、結果であるため、式はブール false なので、レコードは印刷されません。

\nパターンにオプションの先行文字が含まれていない場合、次の改行文字はフィールド区切り文字として解釈されるため、RS各レコードは追加の空白フィールドで終わります。something1レコード区切り文字の一部として、最後のフィールドの後に改行文字が必要です。ファイルはレコード区切り文字で始まり、先頭に改行文字がないため、オプションでなければなりません。それなしで私達はこれを得ます:

$ gawk -v RS='[–-]\n' -v FS='\n' -v OFS=', ' '$1 = $1' data
Jun 6th, something2, 09:00, some text blah blah, something1,
Jun 6th, something1, 09:00, some text xxx, something1,

追加の空のフィールドが原因で追加のコンマが発生しました。

答え3

trコマンドとsedコマンドを使用してこれを実行できます。

$ tr '\n' ',' <input_file | sed 's/-,/\n/g' | sed 's/.$//'

Jun 6th,something2,09:00,some text blah blah,something1
Jun 6th,something1,09:00,some text xxx,something1

(2番目のsedは末尾のカンマを削除します)

ダッシュ区切り文字が入力ファイルで同じであることを確認する必要があります。このコードをテストするためにコピーしたときはそうではありませんでした。

答え4

something*入力に引用符やカンマが含まれている可能性があり、レコードに改行がなく、実際のsome text*レコード区切り文字のみを持つ有効なCSV出力が必要な場合、潜在的な解決策を-テストするための入力ファイルは次のとおりです。

$ cat file
-
Jun 6th
something2
09:00
"some "text" blah blah"
"something1"
-
Jun 6th
something1
09:00
some, text, xxx
something1
-

以下は、有効なCSV出力であるPOSIX awkを使用するソリューションです。

$ cat tst.awk
$1 == "-" {
    if ( NR > 1 ) {
        print ""
    }
    sep = ""
    next
}
/[",]/ {
    gsub(/^"|"$/,"")
    gsub(/"/,"\"\"")
    $0 = "\"" $0 "\""
}
{
    printf "%s%s", sep, $0
    sep = ","
}

$ awk -f tst.awk file
Jun 6th,something2,09:00,"some ""text"" blah blah","something1"
Jun 6th,something1,09:00,"some, text, xxx",something1

これが入力に必要な出力ではない場合は、質問の例を編集して、,入力にsとsがある場合を処理する方法を示します。"

関連情報