シェルコマンドを使用して、テキストファイルの最初の列と最後の列のみを表示する方法は?


30

テキストファイルの最初の列と最後の列のみを表示するためにsedコマンドを使用する方法を理解するには、助けが必要です。これが私がこれまでコラム1に持っていたものです。

cat logfile | sed 's/\|/ /'|awk '{print $1}'

最後の列を表示するための私の弱い試みは次のとおりでした:

cat logfile | sed 's/\|/ /'|awk '{print $1}{print $8}'

ただし、これは最初の列と最後の列を取り、それらを1つのリストにマージします。sedおよびawkコマンドで最初の列と最後の列を明確に印刷する方法はありますか?

サンプル入力:

foo|dog|cat|mouse|lion|ox|tiger|bar

5
サンプル入力を提供してください。
jasonwryan

回答:


51

ほぼそこに。両方の列参照を並べて配置するだけです。

cat logfile | sed 's/|/ /' | awk '{print $1, $8}'

また、catここでは必要ないことに注意してください。

sed 's/|/ /' logfile | awk '{print $1, $8}'

またawk、列の区切りが|空白ではなくであるためsed、どちらも必要ないことを確認できます。

awk -F '|' '{print $1, $8}' logfile

あたりとして提案することによりカレブ、あなたはまだ正確に8がない場合であっても、最後のフィールドを出力ソリューションをしたい場合は、使用することができます$NF

awk -F '|' '{print $1, $NF}' logfile

また、出力を保持したい場合 |スペースを使用する代わりに区切り文字場合は、出力フィールドの区切り文字を指定できます。残念ながら、-Fフラグを使用するよりも少し不器用ですが、次の3つの方法があります。

  • awkBEGINブロックで、入力フィールドと出力フィールドの区切り文字をそれ自体で割り当てることができます。

    awk 'BEGIN {FS = OFS = "|"} {print $1, $8}' logfile
  • これらの変数awkは、コマンドラインから-vフラグを介して呼び出すときに割り当てることができます。

    awk -v 'FS=|' -v 'OFS=|' '{print $1, $8}' logfile
  • または単に:

    awk -F '|' '{print $1 "|" $8}' logfile

4
この問題をどのように単純化できるかを分析する良い仕事。|文字列の連結にデフォルトのスペースの代わりに出力セパレーターとして使用する方法についてのメモを追加できます。また、最後の列を取得するため$NFにハードコーディングの代わりに使用するように説明することもでき$8ます。
カレブ

12

ただ、最初から最後まで交換する||(またはスペースあなたが好む場合):

sed 's/|.*|/|/'

特別なsed実装は|ありませんが(拡張正規表現が実装によって-Eまたは-r一部の実装で有効化されていない限り)、\|それ自体はGNUのような特別な実装sedです。そのため、文字と一致させるつもりならエスケープし|ないでください|

スペースで置き換える場合、および入力にすでに1つだけの行が含まれている可能性がある場合は、それらが一致しないもの|として特別に処理する必要があります|.*|。それは次のとおりです。

sed 's/|\(.*|\)\{0,1\}/ /'

(つまり、.*|一部をオプションにします)または:

sed 's/|.*|/ /;s/|/ /'

または:

sed 's/\([^|]*\).*|/\1 /'

入力のフィールドの数に関係なく最初と8番目のフィールドが必要な場合は、次のようにします。

cut -d'|' -f1,8


(これらはすべて、入力が有効なテキストを形成していることを前提として、POSIX準拠のユーティリティで動作します(特に、sed入力に現在のロケールで有効な文字を形成しないバイトまたはバイトシーケンスが入力に含まれている場合printf 'unix|St\351phane|Chazelas\n' | sed 's/|.*|/|/'、 UTF-8ロケール))。


11

awkとにかく使用しています:

awk '{ print $1, $NF }' file

2
入力フィールドの区切り文字を指定する必要はありませんか(この場合|は、むしろそのスペースであると思われるため)-F\|または同様ですか?また、出力に同じ区切り文字を使用したい場合はどうなりますか?
カレブ

おそらく@Caleb:私は何を確認するためにOPを待っていたまさに ...入力はむしろ非稼働例に基づいて推測しようとするよりも、ように見えた
jasonwryan

1
入力には少なくとも2つのフィールドが含まれることを前提としていることに注意してください。
ステファンシャゼル14年

@StéphaneChazelasOPは、常に8つのフィールドがあることをコードで明確に述べています。
michaelb958

3
@ michaelb958私は「明らかに」ケースを誇張していると思います、ほんの少し:)
jasonwryan 14年

4

自分がawkやsedを使わないことに気付いたら、coreutilsで同じことを実現できます。

paste <(           cut -d'|' -f1  file) \ 
      <(rev file | cut -d'|' -f1 | rev)

cut最初の列にだけ興味がある場合、または区切り文字が固定されている(つまり、可変数のスペースではない)場合は、awk / sedよりもクリーンでコンパクトです。
スリダールサルノバト

2

で区切られているテキストの最初と最後のフィールドを取得しようとしているようです|

ログファイルには次のようなテキストが含まれていると想定しましたが、

foo|dog|cat|mouse|lion|ox|tiger|bar
bar|dog|cat|mouse|lion|ox|tiger|foo

そして、次のような出力が必要です。

foo bar
bar foo

はいの場合、ここにコマンドがあります

GNU sedを介して、

sed -r 's~^([^|]*).*\|(.*)$~\1 \2~' file

例:

$ echo 'foo|dog|cat|mouse|lion|ox|tiger|bar' | sed -r 's~^([^|]*).*\|(.*)$~\1 \2~'
foo bar

列はパイプで区切られていません| しかし、それらは列にあり、私はsedを使用することに興味がありますが、コマンドで行ったようにawkコマンドを使用しません:sed -r 's〜^([^ |] *)。* \ |(。*)$〜\ 〜」ファイル1 \ 2
user70573

「列はパイプで区切られていませんが、列の中にあります」ということは、列がスペースで区切られているということですか?
アビナッシュラジ14年

サンプルの入力と出力の方が良いでしょう。
アビナッシュラジ14年

1

あなたはおそらくそれを行うべきsedです-私はとにかく-しかし、誰もまだこれを書いていないので:

while IFS=\| read col1 cols
do  printf %10s%-s\\n "$col1 |" " ${cols##*|}"
done <<\INPUT
foo|dog|cat|mouse|lion|ox|tiger|bar
INPUT

出力

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