다음 형식의 파일이 있습니다.
[#] OWNER_NAME NAME SIZE
[6] Robottinosino Software 200
[42] Robottinosino Ideas worth zero 188
[12] Robottinosino Ideas worth zero or more 111
[13] I am Batman Hardware 180
[25] Robottinosino Profile Pictures 170
명령줄 도구를 사용하여 다음을 수행하고 싶습니다.
my_command "Ideas worth zero"
다음 결과를 얻습니다.
42
다음 결과를 얻을 위험은 없습니다.
12
grep을 사용하여 첫 번째 필드를 가져오는 awk라는 줄을 식별하려고 생각했지만 텍스트 'OWNER_NAME' 및 'SIZE'가 어느 열에 있는지 계산하는 것 외에 전체 'NAME' 필드를 안정적이고 효율적으로 일치시키는 방법을 잘 모르겠습니다. 헤더에 나타나고 약간의 공백을 제거하여 그 사이의 모든 것을 가져옵니다.
'OWNER_NAME'은 두 단어 이상일 수 있습니다. 예: 'OWNER_NAME' = "I am Batman".
구현과 관련된 아이디어가 있습니까?
여기서 알아야 할 것은 cat, head, tail, awk, sed, grep, cut 등의 오래된 계열입니다.
답변1
좋아요, 열의 길이를 알 수 없다면 bash보다 더 강력한 언어로 전환하겠습니다.
#!/usr/bin/perl
use warnings;
use strict;
my $string = shift;
open my $FH, '<', '1.txt' or die $!;
my $first_line = <$FH>;
my ($before, $name) = $first_line =~ /(.* )(NAME *)/;
my $column = length $before;
$string .= ' ' x (length($name) - length $string); # adjust the length of $string
while (<$FH>) {
if ($column == index $_, $string, $column) {
/^\[([0-9]+)\]/ and print "$1\n";
}
}
답변2
필드 너비가 일정한 경우(예: 필드 너비로 표시된 파일 형식이 최대값인 경우) GNU awk( gawk(1)
)를 사용하고 FIELDWIDTHS
고정 너비 구문 분석을 사용하도록 변수를 설정할 수 있습니다.
gawk -v searchstr="Ideas worth zero" -- '
BEGIN { FIELDWIDTHS="6 15 27 5" } # assuming the final field width is 5
# Pre-process data
{
gsub(/[^[:digit:]]/, "", $1) # strip out non-numbers
for (i = 2; i <= NF; i++)
gsub(/[[:space:]]*$/, "", $i) # strip trailing whitespace
}
# match here
$3 == searchstr { print $1 }
' file.txt
이를 쉘 스크립트나 함수로 래핑하고 매개변수화할 수 있습니다 searchstr
( -v searchstr="$1"
).
그러나 필드가 가변 너비인 경우(즉, 데이터가 변경되면 필드 너비가 변경될 수 있음) 첫 번째 줄을 검사하여 필드 너비를 좀 더 영리하고 동적으로 결정해야 합니다. 하나의 필드가 밑줄을 사용하여 호출되는 경우 OWNER_NAME
필드 이름에 공백이 없다고 가정하므로 공백이 필드 이름을 구분한다고 가정할 수 있습니다.
이를 정의하면 해당 BEGIN...
줄을 다음 코드로 바꿀 수 있습니다.
NR == 1 {
for (i = 2; i <= NF; i++)
FIELDWIDTHS=FIELDWIDTHS index($0" ", " "$i" ")-index($0" ", " "$(i-1)" ") " "
FIELDWIDTHS=FIELDWIDTHS "5" # assuming 5 is the width of the last field
next
}
그러면 첫 번째 줄의 필드를 보고 두 번째 필드와 마지막 필드의 후속 필드 위치 간의 차이를 계산하여 필드 너비를 계산합니다. 나는 마지막 필드의 너비가 5라고 가정했지만 거기에 큰 숫자를 입력하면 남은 내용에도 작동할 것이라고 생각합니다.
NAME
내부에서 찾을 수 없도록 OWNER_NAME
(또는 이라는 필드가 있는 경우 ) 이름 앞뒤에 공백을 찾아야 하며 , 대신 전체 필드와 일치해야 합니다(또한 일치할 수 있도록 OWNER
공백을 추가해야 합니다). $0
거기에 아무것도 없더라도 끝에 공간이 있습니다).
에서만 일치하는 대신 필드 이름으로 쿼리할 수 있도록 더 멋지게 만들 수 있지만 $3
그건 여러분에게 맡기겠습니다.
답변3
아마도 '0의 가치가 있는 아이디어'로 먼저 행을 필터링한 다음 '... 또는 그 이상' 행을 던지는 것이 가장 간단할 것입니다.
grep 'Ideas worth zero' | grep -v 'Ideas worth zero or more'
그리고 해당 파이프에서 숫자를 얻으려면 입력을 다음과 같이 하십시오.
cut -d' ' -f1 | tr -d ']['
공백으로 구분된 첫 번째 필드를 잘라내고 대괄호를 제거합니다.
적절한 필드 구분 기호가 제공되는 방식으로 파일 형식을 약간 변경할 수 있다면 가장 좋습니다.
답변4
이는 다음과 같은 도움이 될 수 있습니다.
function my_command () {
sed -n $(cut -b22-48 1.txt |
grep -n "$1"' *$' |
cut -f1 -d: )p 1.txt \
| cut -d' ' -f1 | tr -d ']['
}
입력에서 관련 열만 잘라내고 문자열이 나타나는 줄 번호를 검색한 다음 이 줄을 가져와서 첫 번째 열의 번호만 유지합니다.