다음과 같이 XML 형식의 날짜가 포함된 텍스트 파일이 많이 있습니다.
<DATA2020-04-13T08:59:05.427 />
다음과 같이 변경해야 합니다.
<DATA>2020-04-13T08:59:05.427</DATA>
노트:
날짜와 시간은 문자열마다 다르며 변경할 수 없습니다. 각 줄의 앞과 뒤에는 XML 형식의 콘텐츠가 더 많이 나옵니다. 또한 Unix를 사용하는 date
것은 선택 사항이 아니며 실제로 파일 내부의 XML 문자열을 변경해야 합니다.
sed
// 찾기 및 바꾸기를 사용하려고 합니다 awk
. perl
아마도 와일드카드를 사용할 수도 있습니다. 누구든지 이것을 달성하는 방법을 생각할 수 있습니까?
답변1
$ echo '<DATA2020-04-13T08:59:05.427 />' | sed -E 's/<DATA(20[^/]*) \/>/<DATA>\1<\/DATA>/'
<DATA>2020-04-13T08:59:05.427</DATA>
또는 이스케이프 s를 백슬래시하지 않아도 되도록 =
구분 기호로 대신 사용하세요 ./
/
$ echo '<DATA2020-04-13T08:59:05.427 />' | sed -E 's=<DATA(202[^/]*) />=<DATA>\1</DATA>='
<DATA>2020-04-13T08:59:05.427</DATA>
이렇게 하면 읽기가 더 쉬워집니다(물론 이제 =
검색 패턴과 대체 텍스트의 모든 문자를 이스케이프해야 합니다).
Perl에서도 거의 동일한 정규식을 사용할 수 있습니다(주요 차이점은 \1
Perl에서 캡처 그룹을 참조하는 것이 더 좋고 정확하다는 것입니다). 구분 연산자에 대한 $1
더 많은 옵션이 있습니다 (예: Match pair sum ).s
{
}
$ echo '<DATA2020-04-13T08:59:05.427 />' |
perl -pe 's{<DATA(202[^/]*) />}
{<DATA>$1</DATA>}'
<DATA>2020-04-13T08:59:05.427</DATA>
Perl에는 대괄호 표현식과 함께 또는 대괄호 표현식 내에서 이스케이프되지 않는 공백(개행 포함)을 /x
무시하는 수정자가 있습니다 . 댓글 \
도 무시합니다 #
. 그 목적은 코드에서 더 읽기 쉽고 문서화된 정규식을 더 쉽게 작성할 수 있도록 하는 것입니다.
man perlre
Perl 정규식에 대한 자세한 내용은 참고자료를 참조하세요.
답변2
ERE 인식 sed -E
(예: GNU 또는 BSD sed)를 사용하세요.
$ sed -E 's:<(DATA)([^ ]+) />:<\1>\2</\1>:' file
<DATA>2020-04-13T08:59:05.427</DATA>
그렇지 않으면 모든 Unix 시스템의 모든 쉘에서 sed를 사용하십시오.
$ sed 's:<\(DATA\)\([^ ]*\) />:<\1>\2</\1>:' file
<DATA>2020-04-13T08:59:05.427</DATA>
답변3
사용행복하다(이전 Perl_6)
raku -pe 's:g/ \<DATA ( <+[0..9]+[-T:.]>+ ) \s\/\> /{"<DATA>"~$0~"</DATA>"}/;'
또는
raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = ["<DATA>"~$0~"</DATA>"];'
입력 예:
<DATA2020-04-13T08:59:05.427 />
예제 출력:
<DATA>2020-04-13T08:59:05.427</DATA>
위는 코드화된 답변입니다.행복하다, Perl 프로그래밍 언어 계열의 구성원입니다. 위의 두 예는 주목할 만한 네 가지 일반적인 특징을 공유합니다.
백슬래시 문자를 추측할 필요가 없습니다. 백슬래시 문자가 아닌 경우
<alnum>
(영숫자 또는 밑줄) 이스케이프해야 합니다./g
지금과 같은 정규식 수정자는global
형식의 시작 부분 바로 뒤에 콜론이 옵니다. 또는 유효합니다.s///
s
s:global
s:g
Perl의
/x
수정자는 이제 Raku의 기본값입니다(정규 표현식 원자 사이에 여유 공간 허용).Raku의 문자열 연결은
~
물결표를 사용하여 수행됩니다.
위의 두 예제 모두 열거된 문자 클래스를 사용합니다 <+[0..9]+[-T:.]>
. 이는 매우 간단하게 숫자 [ 0..9
]에 4개의 문자 [ -
T
:
.
]를 더한 것입니다. 또한 위의 첫 번째 예는 전통적인 s///
대체 관용구를 따르는 반면, 위의 두 번째 예는 Raku의 새로운 "백슬래시 없음" 대체 형식( =
중간에 등호 포함)을 사용하는데, 일부 독자는 이 형식이 더 읽기 쉽다고 생각할 수 있습니다.
마지막으로, 날짜/시간 추출/수정에 관심이 있는 경우 Raku에서 다음을 다루었습니다.
~$ echo '<DATA2020-04-13T08:59:05.427 />' | raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = [DateTime($0~"Z")];'
2020-04-13T08:59:05.427000Z
~$ echo '<DATA2020-04-13T08:59:05.427 />' | raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = [DateTime(now) - DateTime($0~"Z")];'
54862286.622457
https://docs.raku.org/언어/regexes#Enumerated_character_classes_and_ranges
https://docs.raku.org/routine/DateTime
https://raku.org