cities
다음과 같은 파일이 있습니다.
[1598] San Diego, US (inactive)
[4517] St Louis, US (inactive)
[6346] Orlando, US (inactive)
나는 다음과 같이 도시 이름을 잘라내고 싶습니다.
San Diego
St Louis
Orlando
이것이 내가 생각해 낼 수 있는 최선의 방법입니다:
cut -d ',' -f1 cities | cut -d ']' -f2
하지만 이름 앞에 여전히 공백이 남아 있습니다. cut
계속할 수 있도록 여러 문자를 구분 기호로 허용하는 유사한 명령이 있습니까 ]
?
답변1
앗(또한 확인이상한 정보) 이런 유형의 문제에는 아름답습니다. 노력하다:
awk -F'[],] *' '{print $2}' cities
이는 필드 구분 기호를 -F
다음과 같이 정의합니다 [],] *
. 이는 닫는 대괄호 또는 쉼표가 한 번 발생하고 그 뒤에 공백이 0개 또는 여러 개가 오는 것을 의미합니다. 물론 어떤 요구 사항에도 맞게 변경할 수 있습니다. 정규식을 읽어보세요.
라인을 분할한 후 분할 결과에 대해 원하는 작업을 수행할 수 있습니다. 여기서는 print 두 번째 필드를 사용하기로 결정했습니다 print $2
. awk 지시문 주위에 작은따옴표를 사용하는 것이 중요합니다. 그렇지 않으면 $2가 쉘로 대체됩니다.
답변2
cut
파이프라인의 마지막 항목을 수정하여 다음을 수행할 수 있습니다.
cut -d ' ' -f2-
위의 의미는 필드 구분 기호가 공백이고 두 번째 필드부터 시작하여 모든 필드를 선택한다는 것입니다. 전체 순서는 다음과 같습니다.
cut -d ',' -f1 cities | cut -d ' ' -f2-
답변3
답변4
sed와 grep이 너무 어려워지면 주로 Perl을 사용합니다.
Perl에서 이것을 작성하는 방법에는 여러 가지가 있습니다. 예를 들어, 속도가 빠르기를 원할 수도 있고 입력에서 예상치 못한 사소한 문제(예: 두 개의 공백이 예상되는 경우)를 처리하기를 원할 수도 있습니다.
명확한 접근 방식(id는 숫자, city는 문자, state는 문자라고 가정):
while (<>) {
if (/^\[\d+\] (\w+(?: \w+)*), \w+ \(\w*\)$/) {
my $city = $1;
print "$city\n";
}
}
또는 느리지만 더 관대합니다(역추적을 더 많이 수행함).
while (<>) {
if (/^.*\]\s+(.*),.*$/) {
my $city = $1;
print "$city\n";
}
}
또는 훨씬 더 빠릅니다(필드는 닫는 대괄호가 처음 나타날 때 중지됨).
while (<>) {
if (/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/) {
my $city = $1;
print "$city\n";
}
}
스크립트 대신 명령줄에서 기본적으로 루프를 -n
추가하는 이 옵션을 사용할 수 있습니다.while (<>) { BLOCK }
perl -ne '/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/ and print $1, "\n";' cities
또는 cut과 유사한 사용법을 원하는 경우 -F
awk의 옵션과 유사한 이 옵션을 사용할 수 있습니다 -F
. 예를 들면 다음 과 같습니다.
perl -a -n -F'/[],]\s+/' -e 'print $F[1], "\n"' cities
이 방법은 어떤 필드에도 구분 기호가 포함되지 않는다고 분명히 가정합니다.