一方file
:
2018-03-22 foo/bar/baz
2020-09-30 Lorem/ipsum/dolor
2021-10-01 yadda/yadda/yadda
2022-03-14 blah/blah/blah
(実際のファイルにはこのような数千行が含まれています)
文字列を取得する方法2018-03-22_2022-03-14
?これは、レコード1のフィールド1、下線、最後のレコードのフィールド1を連結したものです。
私はこれを思い出しました:
$ awk 'BEGIN{ORS="_"}NR==1{print $1} END{print $1}' file | sed 's/_$//'
2018-03-22_2022-03-14
働くが複雑ではないawk
sed
パイプやサブシェルだけを使用したり使用したりすることなく、同じ結果を得る方法です。実際にそのような方法がありますか?
答え1
専用バージョンsed
:
sed 's/ .*//;1h;$!d;H;g;y/\n/_/' file
s/ .*//
スペースの後ろのすべての項目を削除し、日付のみを保持するために使用されます。1h
1
空白に行の日付をコピーhold
$!d
d
最後の行を除くすべての行を削除- ここに到着すると、最後の行にあるため、
H
最初の日付を含むこの行を前のスペースに追加してから、両方をパターンスペースにコピーします。g
- 今残っている唯一のことは、挿入された改行(追加のため)を下線に置き換えることです。
y/\n/_/
(あなたは少し短いです)
答え2
移植性のためにこのセクションで実装print $1
(または使用$anything
)しないでくださいEND
。これは、このセクションの対応するエントリが$0
POSIX に従って定義されていない動作であるためです。一部のawksでは、この部分が最後の行から読み取られた最初のフィールドの値になり、他の場合はnullになり、他の場合は別の値になることがあります。$1
END
$1
END
すべてのUnixシステムのすべてのシェルでawkを使用してください。
$ awk -v OFS='_' 'NR==1{beg=$1} {end=$1} END{print beg, end}' file
2018-03-22_2022-03-14
_
または、入力ファイルが空の場合は、単一のファイルを印刷しないでください。
awk -v OFS='_' 'NR==1{beg=$1} {end=$1} END{ if (NR) print beg, end}' file
上記は、入力に行が1つしかない場合、その行間$1
で同じ値が繰り返されることを前提としています_
。これが望ましくない場合は、質問を更新してこのケースの要件を明確にしてください。
答え3
出力制御の場合printf
:
$ awk 'NR==1{printf("%s_", $1)}END{print $1}' f
2018-03-22_2022-03-14
答え4
大容量ファイルの処理に時間がかかるため、大容量入力ファイルを使用することをお勧めしますhead
。tail
awk
sed
$ cat input.txt
2018-03-22 foo/bar/baz
2020-09-30 Lorem/ipsum/dolor
2021-10-01 yadda/yadda/yadda
2022-03-14 blah/blah/blah
{ head -n1 input.txt && tail -n1 input.txt; } |
cut -d ' ' -f1 | paste -sd _ -
2018-03-22_2022-03-14