다음과 같은 입력을 얻으십시오.
08/22/2019 12:00:58
Name Cans Bucks Puns
Clyde 12 2 79
Sheila 32 16 42
Elmo 44 18 21
08/23/2019 19:00:22
Name Cans Bucks Puns
Clyde 18 21 46
Sheila 37 2 11
Elmo 41 3 10
다음과 같이 출력됩니다.
name=Clyde cans=12 bucks=2 puns=79 ts=1566475258
name=Sheila cans=32 bucks=16 puns=42 ts=1566475258
name=Elmo cans=44 bucks=18 puns=21 ts=1566475258
name=Clyde cans=18 bucks=21 puns=46 ts=1566586822
name=Sheila cans=37 bucks=2 puns=11 ts=1566586822
name=Elmo cans=41 bucks=3 puns=10 ts=1566586822
나는 awk를 사용하여 이를 달성하려고 시도했지만 성공하지 못했습니다(완전히 당황한 시간 변환 제외).
내가 얻은 가장 가까운 것은 다음과 같습니다.
ts=08/22/2019 12:00:58
name=Clyde cans=12 bucks=2 puns=79
name=Sheila cans=32 bucks=16 puns=42
name=Elmo cans=44 bucks=18 puns=21
ts=08/23/2019 19:00:22
name=Clyde cans=18 bucks=21 puns=46
name=Sheila cans=37 bucks=2 puns=11
name=Elmo cans=41 bucks=3 puns=10
awk가 최고의 도구인지조차 확신할 수 없습니다.
답변1
awk -F'[/: ]' '{
if (NF==6){
ts=mktime($3" "$1" "$2" "$4" "$5" "$6)
skipheader=1
}
else if (NF==0 || skipheader){
skipheader=0
}
else {
print "name="$1,"cans="$2,"bucks="$3,"puns="$4,"ts="ts
}
}' file
/
:
별도의 날짜 및 시간 부분을 얻으려면 , 및 공백 문자를 사용하여 필드를 분할하십시오 .- 필드 수가 6개인 경우 타임스탬프를 만들고
ts
다음 헤더 행을 건너뛰도록 플래그를 설정합니다. - 필드 수가 0이거나
skipheader
플래그가 설정된 경우skipheader
플래그를 재설정합니다. - 그렇지 않으면 데이터를 인쇄하십시오.
산출:
name=Clyde cans=12 bucks=2 puns=79 ts=1566468058
name=Sheila cans=32 bucks=16 puns=42 ts=1566468058
name=Elmo cans=44 bucks=18 puns=21 ts=1566468058
name=Clyde cans=18 bucks=21 puns=46 ts=1566579622
name=Sheila cans=37 bucks=2 puns=11 ts=1566579622
name=Elmo cans=41 bucks=3 puns=10 ts=1566579622
답변2
다음 Perl 스크립트는 입력의 필드 수와 필드 이름에 관계없이 작동합니다.
소요된다시간::날짜그리고목록::추가 유틸리티라이브러리 모듈. 이 두 가지는 배포용으로 이미 패키지되어 있을 수 있습니다(예: debian sudo apt-get install libtimedate-perl liblist-moreutils-perl
). 이러한 모듈이 필요하지 않도록 스크립트를 작성하는 것이 가능하지만 기존 재사용 가능한 라이브러리 코드가 필요한 작업을 정확하게 수행할 때 바퀴를 다시 만들 필요는 없습니다.
스크립트는 입력 줄이 공백 수(예: 하나 이상의 공백, 탭 등)로 구분되어 있다고 가정합니다. 입력이 탭으로 구분된 경우 줄을 split;
로 변경합니다 split /\t/;
. 첫 번째 필드의 이름에 공백이 포함되어 있거나(예: ) 필드 이름에 공백이 포함된 경우 Firstname Surname
탭 구분 기호를 사용하는 것이 좋습니다 .
예를 들어 특정 시간대를 하드코딩해야 하는 경우 GMT
다음 줄을 변경합니다.
$ts = str2time($_);
예를 들어(앞의 따옴표 안의 공백에 유의하세요 GMT
):
$ts = str2time($_ . ' GMT');
#!/usr/bin/perl
use strict;
use Date::Parse;
use List::MoreUtils qw(pairwise);
my @columns;
my $ts='';
while(<>) {
s/^\s*|\s*$//g; #/ strip leading and trailing spaces
next if (/^$/); #/ skip empty lines
chomp;
# line begins with two digits and a slash? it's a date.
if (m/^\d\d\//) {
# get the date and parse it so that we have seconds since the epoch
$ts = str2time($_);
# get the next line and split it into column headers
$_ = readline;
@columns = split;
} else {
# split the current line into @row array
my @row=split;
# use pairwise() function from List::MoreUtils module to merge the
# @columns and @row arrays.
print join(" ", (pairwise { "$a=$b" } @columns, @row), "ts=$ts"), "\n";
}
}
예제 출력:
$ ./reformat.pl input.txt
Name=Clyde Cans=12 Bucks=2 Puns=79 ts=1566439258
Name=Sheila Cans=32 Bucks=16 Puns=42 ts=1566439258
Name=Elmo Cans=44 Bucks=18 Puns=21 ts=1566439258
Name=Clyde Cans=18 Bucks=21 Puns=46 ts=1566550822
Name=Sheila Cans=37 Bucks=2 Puns=11 ts=1566550822
Name=Elmo Cans=41 Bucks=3 Puns=10 ts=1566550822
참고: 데이터 행에 열 머리글 수보다 많거나 적은 열이 있는 경우 완전히 중단되지는 않지만 비정상적인 출력이 생성됩니다. 누락된 필드의 경우 부호는 있지만 값은 없는 필드 이름만 인쇄합니다 =
(예: 입력 줄에 필드가 2개만 있는 경우 출력). 필드가 더 많은 경우 접두사가 Puns=
붙은 값만 인쇄합니다( =
예를 들어 , 입력 라인에 값이 20인 추가 필드가 있으면 출력됩니다 =20
.
예를 들어, 예시 입력에 다음과 같은 세 번째 데이터 블록이 있는 경우:
08/23/2019 23:30:01
Name Cans Bucks Puns
Clyde 18 21 46
Sheila 37 2 11
Elmo 41 3 10
Missing 41 3
Extra 41 3 10 20
그러면 추가 출력이 발생합니다.
Name=Clyde Cans=18 Bucks=21 Puns=46 ts=1566567001
Name=Sheila Cans=37 Bucks=2 Puns=11 ts=1566567001
Name=Elmo Cans=41 Bucks=3 Puns=10 ts=1566567001
Name=Missing Cans=41 Bucks=3 Puns= ts=1566567001
Name=Extra Cans=41 Bucks=3 Puns=10 =20 ts=1566567001