다음 파일(somefile.txt)이 있습니다.
/A/1/B/1/C/1/D/1/E/1/F/2/G/1/H/1/I/1/J/1/K/1/
/B/1/C/1/D/1/E/1/F/5/G/1/H/1/I/1/J/1/K/1/
/C/1/D/1/E/1/F/9/G/1/H/1/I/1/J/1/K/1/
/D/1/E/1/F/7/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/8/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/3/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/6/G/1/H/1/I/1/J/1/K/1/
/B/1/C/1/D/1/E/1/F/8/G/1/H/1/I/1/J/1/K/1/
/D/1/E/1/F/3/G/1/H/1/I/1/J/1/K/1/
/C/1/D/1/E/1/F/6/G/1/H/1/I/1/J/1/K/1
나는 다음 결과를 원합니다 (뒤의 다음 숫자 F
):
2
5
9
7
8
3
6
8
3
6
행당 열 수가 가변적이라면 다음과 같이 할 수 있는 방법이 있습니까? :
awk -F'/' '/F/ {print <column_of_match> + 1 }' somefile.txt
답변1
Perl을 사용하면 배열 분할이 편리하므로 배열의 각 요소 쌍을 해시의 키와 값으로 처리할 수 있습니다.
$ perl -F/ -lane '%f = @F[1..$#F]; print $f{F}' input.txt
2
5
9
7
8
3
6
8
3
6
Perl -F
및 -a
(자동 분할)은 awk와 유사하게 작동하지만 행을 자동으로 $1, $2, $3 등으로 분할하는 대신 각 행을 이라는 배열로 자동 분할합니다 @F
.
이 스크립트는 @F
배열 슬라이스(0번째 요소를 제외한 모든 요소)를 이름이 지정된 해시(연관 배열)로 변환하고 %f
키 "F"를 사용하여 요소를 인쇄합니다.%f
기능/작동 방식(그리고 빈 문자열인 @F의 0번째 요소를 제외해야 하는 이유)을 강조하기 위해 사용 @F
시 다음 %f
과 같습니다 .데이터::덤프모듈 dump
기능:
$ perl -F/ -MData::Dump=dump -lane '
%f = @F[1..$#F];
print join("\n", $_, dump(@F), dump(\%f), $f{F}), "\n"' input.txt
/A/1/B/1/C/1/D/1/E/1/F/2/G/1/H/1/I/1/J/1/K/1/
("", "A", 1, "B", 1, "C", 1, "D", 1, "E", 1, "F", 2, "G", 1, "H", 1, "I", 1, "J", 1, "K", 1)
{ A => 1, B => 1, C => 1, D => 1, E => 1, F => 2, G => 1, H => 1, I => 1, J => 1, K => 1 }
2
/B/1/C/1/D/1/E/1/F/5/G/1/H/1/I/1/J/1/K/1/
("", "B", 1, "C", 1, "D", 1, "E", 1, "F", 5, "G", 1, "H", 1, "I", 1, "J", 1, "K", 1)
{ B => 1, C => 1, D => 1, E => 1, F => 5, G => 1, H => 1, I => 1, J => 1, K => 1 }
5
/C/1/D/1/E/1/F/9/G/1/H/1/I/1/J/1/K/1/
("", "C", 1, "D", 1, "E", 1, "F", 9, "G", 1, "H", 1, "I", 1, "J", 1, "K", 1)
{ C => 1, D => 1, E => 1, F => 9, G => 1, H => 1, I => 1, J => 1, K => 1 }
9
...and so on...
F
참고: 입력 내용이 없으면 빈 줄이 인쇄됩니다. 이것이 원하는 것이 아닐 경우 다음을 수행하십시오.
perl -F/ -lane '%f = @F[1..$#F];
if (defined $f{F}) {
print $f{F}
} else {
print STDERR "Error on input line $.: F has absconded"
}' input.txt
답변2
사용된 답변은 다음과 같습니다 sed
.
$ sed -n 's|.*F/\([0-9]\).*|\1|p' <<EOF
/A/1/B/1/C/1/D/1/E/1/F/2/G/1/H/1/I/1/J/1/K/1/
/B/1/C/1/D/1/E/1/F/5/G/1/H/1/I/1/J/1/K/1/
/C/1/D/1/E/1/F/9/G/1/H/1/I/1/J/1/K/1/
/D/1/E/1/F/7/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/8/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/3/G/1/H/1/I/1/J/1/K/1/
/A/1/B/1/C/1/D/1/E/1/F/6/G/1/H/1/I/1/J/1/K/1/
/B/1/C/1/D/1/E/1/F/8/G/1/H/1/I/1/J/1/K/1/
/D/1/E/1/F/3/G/1/H/1/I/1/J/1/K/1/
/C/1/D/1/E/1/F/6/G/1/H/1/I/1/J/1/K/1
EOF
2
5
9
7
8
3
6
8
3
6
설명 -n 's|.*F/\([0-9]\).*|\1|p'
:
-n
명시적으로 지시하지 않는 한 아무것도 인쇄하지 않는다는 의미입니다.p
표현식의 꼬리는 "이 표현식이 일치하면 이 줄을 인쇄합니다"를 의미합니다. 이는 기호가 없는 행은F/[0-9]
인쇄되지 않음을 의미합니다.s|foo|bar|
표현의 의미는 다음foo
과 같습니다. 로 대체합니다bar
. 라고 생각하시곤 하는데,s/foo/bar/
표현에 a가 있어서 피하곤 했어요./
|
- 경쟁부분 (
foo
):.*F/[0-9].*
의미:F/
숫자가 포함된 모든 줄..*F/\([0-9]\).*
F/
의미: 숫자가 포함된 전체 줄과 일치하지만 해당 숫자를 기억하세요.
- 교체 부품 (
bar
):\1
우리가 기억하는 숫자를 나타냅니다.
간단히 말해서:
- 일치하는 줄을 찾아
*F/[0-9]*
숫자로만 바꿉니다.
여러 자리 양의 정수를 사용할 수 있으면 표현식을 쉽게 조정할 수 있습니다.
sed -n 's|.*/F/\([0-9]\+\)/.*|\1|p'
답변3
구분 기호와 일치하는 패턴을 사용하여 해당 하위 문자열을 배열로 분할하고 F
하위 필드를 인쇄하면 됩니다.
테스트 코드:
$ awk 'match ($0, "/F/[^/]/") {
split (substr ($0, RSTART, RLENGTH), V, "/");
print V[3];
}' Match.txt
필드를 반복하거나 두 가지 프로세스를 사용할 필요가 없습니다.
문자열 인덱스를 조정하여 split
필요하지 않은 부분을 제거할 수도 있지만 이렇게 하면 활용도가 떨어지고 일회성 오류가 발생할 가능성이 높아집니다.
awk 'match ($0, "/F/[^/]/") {
print substr ($0, RSTART+3, RLENGTH-4);
}' Match.txt
답변4
다음은 awk를 두 번 사용하는 것과 관련된 문제에 대한 가능한 해결책입니다. 한 번은 올바른 위치에서 분할하고 다음 번에는 숫자를 가져와 인쇄합니다.
스크립트는 다음과 같습니다.
awk -F "/F/" '{print $2}' prova.txt | awk -F "/" '{print $1}'
첫 번째 부분에서는 두 번째 부분의 첫 글자가 우리가 찾고 있는 숫자가 되도록 입력 문자열을 분할하고 /F/
스크립트의 두 번째 부분에서는 해당 숫자를 분리합니다.
이것은 한 줄에 최대 하나만 있을 때 작동합니다 F
(빈 줄만 인쇄하므로 F 없이도 작동합니다.