次の形式のテキストファイルがあります。最初の行は「KEY」であり、2行目は「VALUE」です。
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
キーと同じ行に値が必要です。したがって、出力は次のようになります...
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1
$
や,
のような区切り文字を使用できればより良いでしょう:
KEY 4048:1736 string , 3
2行を1行にマージするにはどうすればよいですか?
awk:
awk 'NR%2{printf "%s ",$0;next;}1' yourFile
出力の最後に空の行があることに注意してください。
sed:
sed 'N;s/\n/ /' yourFile
paste
はこのジョブに適しています。
paste -d " " - - < filename
Sed、awk、grepの代替:
xargs -n2 -d'\n'
これは、N行を結合し、スペースで区切られた出力のみが必要な場合に最適です。
私の最初の答えはxargs -n2
で、行ではなく単語で区切ります。 -d
を使用して、任意の1文字で入力を分割できます。
絞首刑よりも犬を殺す方法がたくさんあります。 [1]
awk '{key=$0; getline; print key ", " $0;}'
引用符の中に好きな区切り文字を入れてください。
参照:
awk
の別の方法を次に示します。
awk 'ORS=NR%2?FS:RS' file
$ cat file
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
$ awk 'ORS=NR%2?FS:RS' file
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1
コメントの Ed Morton で示されているように、安全性のためにブレースを追加し、移植性のために括弧を追加する方が適切です。
awk '{ ORS = (NR%2 ? FS : RS) } 1' file
ORS
はOutput Record Separatorの略です。ここで行っているのは、行番号を格納するNR
を使用して条件をテストすることです。 NR
のモジュロが真の値(> 0)である場合、デフォルトでスペースであるFS
(フィールドセパレーター)の値に出力フィールドセパレーターを設定します。それ以外の場合、改行であるRS
(レコードセパレーター)の値を割り当てます。
,
をセパレータとして追加する場合は、次を使用します。
awk '{ ORS = (NR%2 ? "," : RS) } 1' file
Bashでの私のソリューションは次のとおりです。
while read line1; do read line2; echo "$line1, $line2"; done < data.txt
以前のソリューションは機能すると思われますが、ドキュメント内で単一の異常が発生した場合、出力はバラバラになります。以下は少し安全です。
sed -n '/KEY/{
N
s/\n/ /p
}' somefile.txt
「ex」は、sed、awk、grepなどと同じファミリーにあるスクリプト可能な行エディターです。探しているものだと思います。多くの最新のviクローン/後続バージョンにもviモードがあります。
ex -c "%g/KEY/j" -c "wq" data.txt
これは、「KEY」に一致する場合、各行に対して次の行のj oinを実行します。そのコマンドが(すべての行に対して)完了したら、w riteおよびq uitを発行します。
このようなawkを使用して、2組の行を組み合わせることができます。
awk '{ if (NR%2 != 0) line=$0; else {printf("%s %s\n", line, $0); line="";} } \
END {if (length(line)) print line;}' flle
Perlがオプションの場合、次を試すことができます。
Perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt
glenn jackman's answer を使用したわずかなバリエーション:paste
の使用:-d
delimiterオプションの値に複数の文字が含まれる場合、paste
は文字を1つずつ循環し、-s
オプションと組み合わせて、同じ入力ファイルを処理します。
つまり、必要なものは何でも使用でき、セパレーターとエスケープシーケンス\n
を使用して、一度に2行をマージできます。
コンマを使用:
$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string,1
KEY 4192:1349 string,1
KEY 7329:2407 string,2
KEY 0:1774 string,1
およびドル記号:
$ paste -s -d '$\n' infile
KEY 4048:1736 string$3
KEY 0:1772 string$1
KEY 4192:1349 string$1
KEY 7329:2407 string$2
KEY 0:1774 string$1
このcannotが行うことは、複数の文字で構成されるセパレータを使用することです。
おまけに、paste
がPOSIXに準拠している場合、ファイルの最後の行の改行は変更されません。そのため、次のような奇数行の入力ファイルの場合、
KEY 4048:1736 string
3
KEY 0:1772 string
paste
は、最後の行の区切り文字を追加しません。
$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string
次のviコマンドも使用できます。
:%g/.*/j
nawk '$0 ~ /string$/ {printf "%s ",$0; getline; printf "%s\n", $0}' filename
これは
$0 ~ /string$/ ## matches any lines that end with the Word string
printf ## so print the first line without newline
getline ## get the next line
printf "%s\n" ## print the whole line and carriage return
Vimを使用した別のソリューション(参照用)。
ソリューション1:
Vim vim filename
でファイルを開き、コマンド:% normal Jj
を実行します
このコマンドは簡単に理解できます:
その後、ファイルを保存して:wq
で終了します
ソリューション2:
シェルでコマンドvim -c ":% normal Jj" filename
を実行し、ファイルを保存して:wq
で終了します。
(処理を簡単にするために)2行を結合する必要があるが、特定の部分を過ぎたデータを許可する必要がある場合、これが役立つことがわかりました。
data.txt
string1=x
string2=y
string3
string4
cat data.txt | nawk '$0 ~ /string1=/ { printf "%s ", $0; getline; printf "%s\n", $0; getline } { print }' > converted_data.txt
出力は次のようになります。
converted_data.txt
string1=x string2=y
string3
string4
最も簡単な方法は次のとおりです。
sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
Perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ $1}msg;' data.txt > data_merged-lines.txt
-0
は、ファイルを1行ずつ読み取るのではなく、ファイル全体を取得します。pE
はループでコードをラップして出力を出力します。詳細は http://perldoc.Perl.org/perlrun.html ;をご覧ください。^KEY
は、行の先頭で「KEY」に一致し、その後に続くシーケンスの前に、貪欲ではない任意の一致(.*?
)が続きます
\s+
。(\d+)
として再挿入する1つ以上の数字$1
;その後に$
行の終わりが続きます。
\K
は、その左側のすべてを置換から便利に除外するため、{ $1}
は1-2シーケンスのみを置き換えます。 http://perldoc.Perl.org/perlre.html を参照してください。
シェルスクリプトとしてのより一般的なソリューション(複数のフォローアップ行を結合できます)。可視性が必要だったので、これはそれぞれの間に線を追加しますが、それは簡単に修正できます。この例は、「キー」行が:で終わる場所で、他の行はありません。
#!/bin/bash
#
# join "The rest of the story" when the first line of each story
# matches $PATTERN
# Nice for looking for specific changes in bart output
#
PATTERN='*:';
LINEOUT=""
while read line; do
case $line in
$PATTERN)
echo ""
echo $LINEOUT
LINEOUT="$line"
;;
"")
LINEOUT=""
echo ""
;;
*) LINEOUT="$LINEOUT $line"
;;
esac
done