줄의 시작 부분에 고정 줄 ​​잡기


20

grep "^$1"일종의 작품이지만 "$1"grep에서 어떻게 문자를 해석하지 못하도록 탈출 합니까?

아니면 더 좋은 방법이 있습니까?

편집 : 검색하고 싶지 '^$1'않지만 동적으로 삽입 된 고정 문자열은 줄의 시작 부분에있는 경우에만 일치해야합니다. 그것이 내가 의미하는 바입니다 $1.


큰 따옴표 대신 작은 따옴표를 사용하려고 했습니까 grep '^$1'? 예 : ? 아니면 $1쉘이 확장되는 것을 막고 싶지 않습니까?
mnille

@mnille '^ $ 1'을 검색하고 싶지 않지만 행의 시작 부분에만 일치 해야하는 동적으로 삽입 된 고정 문자열을 검색하고 싶습니다. 그것이 제가 $ 1의 의미입니다.
PSkocik

3
당신도 그것을 할 수 grep있지만 먼저 문자열에서 특별한 문자를 탈출해야합니다. 예 :printf %s ^;printf %s "$1" | sed 's/[][\.*^$]/\\&/g'; } | grep -f- infile
don_crissti

@don_crissti 다른 답변보다 낫습니다. 그것을 하나 만드시겠습니까?
roaima

@roaima-알고 있지만 이미 여기에 많은 답변이 있으며 이것은 (vars 내부의 특수 문자를 이스케이프 처리) 꽤 오랫동안 집에 망치고있는 것입니다 ... 항상 추가 할 수 있습니다 원하는 경우 답변에 여기에 주석을 제거합니다 (앞에 누락 된 중괄호를 추가하는 것을 잊지 마십시오).
don_crissti

답변:


7

나는 이것을 사용하여 이것을 할 수있는 방법을 생각할 수 없다 grep. ^자체는 정규 표현식의 일부이므로이를 사용하려면 정규 표현식을 해석해야합니다. 그것은 하위 문자열 일치에 사용 사소한 awk, perl또는 무엇을 :

awk -v search="$1" 'substr($0, 1, length(search)) == search { print }'

을 포함하는 검색 문자열을 처리하려면 123의 답변\ 과 동일한 트릭을 사용할 수 있습니다 .

search="$1" awk 'substr($0, 1, length(ENVIRON["search"])) == ENVIRON["search"] { print }'

\/
123

@ 123 실제로, 나는 그것을 처리하기 위해 변형을 추가했습니다.
Stephen Kitt

여전히 같은 복잡한 문자열을 실패합니다 \\\/\/\/\\\\/즉으로 볼 \\///\\/프로그램이다. 내가 아는 한 미리 얼마나 많은 것이 사용 될지 알지 않는 한 awk에서 백 슬래시를 올바르게 벗어날 수있는 방법이 없습니다.
123

1
@ 123 감사합니다. 탈출 처리를 피하기 위해 환경을 통과하는 트릭을 조정했습니다.
Stephen Kitt

나는 여전히이 솔루션을 가장 좋아합니다. 효율적 (awk + 시간 낭비 없음), 빠른 시작 (awk + 상태 설정에 추가 프로세스 필요 없음) 표준 도구를 사용하며 매우 간결합니다. 다른 모든 답변에는 적어도 이들 중 일부가 부족합니다. grep이 최고의 속도로 알려져 있기 때문에 효율성은 여기서 중요한 포인트입니다.
PSkocik

14

일치하는 것이 있는지 여부 만 확인해야하는 경우 모든 입력 행을 원하는 접두사 길이 ( $1)로 자른 다음 고정 패턴 그렙을 사용하십시오.

if cut -c 1-"${#1}" | grep -qF "$1"; then
    echo "found"
else
    echo "not found"
fi

일치하는 줄의 수를 얻는 것도 쉽습니다.

cut -c 1-"${#1}" | grep -cF "$1"

또는 일치하는 모든 줄의 줄 번호 (줄 번호는 1부터 시작) :

cut -c 1-"${#1}" | grep -nF "$1" | cut -d : -f 1

줄 번호를 입력 head하고 tail일치하는 줄의 전체 텍스트를 얻을 수 있지만, 그 시점에서 Python 또는 Ruby와 같은 최신 스크립팅 언어를 사용하는 것이 더 쉽습니다.

위의 예는 Posix grep and cut을 가정합니다. 검색 할 파일이 표준 입력에서 온 것으로 가정하지만 대신 파일 이름을 사용하도록 쉽게 조정할 수 있습니다.

편집 : 또한 패턴 ( $1)이 길이가 0이 아닌 문자열 인지 확인해야 합니다. 그렇지 않으면 cut말을하지 values may not include zero. 또한 Bash를 사용하는 경우을 사용 set -o pipefail하여 오류 종료를 포착하십시오 cut.


10

백 슬래시를 존중하는 펄을 사용하는 방법

v="$1" perl -ne 'print if index($_, $ENV{"v"} )==0' file

명령에 환경 변수 v를 설정 한 다음 변수의 색인이 0 인 경우 (예 : 행의 시작) 인쇄합니다.

awk에서도 동일하게 할 수 있습니다

v="$1" awk 'index($0, ENVIRON["v"])==1' file

7

텍스트 처리에 bash를 권장하는 것이 아니라 all-bash 옵션이 있지만 작동합니다.

#!/usr/bin/env bash
# searches for $1 at the beginning of the line of its input

len=${#1}
while IFS= read -r line
do
  [[ "${line:0:len}" = "$1" ]] && printf "%s\n" "$line"
done

이 스크립트 len는 입력 된 매개 변수 $ 1 의 길이 를 계산 한 다음 각 줄에서 매개 변수 확장을 사용하여 첫 len문자가 $ 1과 일치 하는지 확인합니다 . 그렇다면 줄을 인쇄합니다.


4

당신이 경우 $1순수 ASCII이고 당신이 grep있다 -P(PCRE를 사용하려면) 옵션을, 당신은이 작업을 수행 할 수 있습니다 :

#!/bin/bash

line_start="$1"
line_start_raw=$(printf '%s' "$line_start" | od -v -t x1 -An)
line_start_hex=$(printf '\\x%s' $line_start_raw)
grep -P "^$line_start_hex"

여기서 grep -P정규 표현식 \xXX을 사용하면 리터럴 문자를 지정할 수 있습니다 . 여기서 XX해당 문자의 16 진 ASCII 값이 있습니다. 특수 정규식 문자 인 경우에도 문자는 문자 그대로 일치합니다.

od는 예상 행 시작을 16 진 값 목록으로 변환하는 데 사용되며, 각 16 진수 값은 접두사로 묶고 \xprintf로 시작 합니다. ^그런 다음 필수 정규 표현식을 작성하기 위해이 문자열 앞에 붙습니다.


$1유니 코드 인 경우에 의해 출력 된 16 진수 바이트와 문자의 1 : 1 대응이 없기 때문에 이것은 조금 더 어려워집니다 od.


3

필터로 :

perl -ne 'BEGIN {$pat = shift} print if /^\Q$pat/' search-pattern

하나 이상의 파일에서 실행하십시오.

perl -ne 'BEGIN {$pat = shift} print if /^\Q$pat/' search-pattern file..

perlre 문서“Quoting metacharacters”섹션에서 설명합니다 :

메타 문자 인용

펄에서 백 슬래쉬 메타 문자와 같은, 영숫자 \b, \w, \n. 다른 정규 표현식 언어와 달리 영숫자가 아닌 백 슬래시 기호는 없습니다. 모습이 좋아하는 무엇이든 있도록 \\, \(, \), \[, \], \{, 또는 \}항상 리터럴 문자가 아닌 메타 문자로 해석됩니다. 이것은 한 번의 공용 관용구에서 패턴에 사용하려는 문자열에서 정규식 메타 문자의 특수 의미를 비활성화하거나 인용하는 데 사용되었습니다. “단어”이외의 문자를 모두 인용하십시오.

    $pattern =~ s/(\W)/\\$1/g;

( use locale설정된 경우 현재 로케일에 따라 다릅니다.) 오늘날에는 모든 메타 문자의 특수 의미를 비활성화 하기 위해 quotemeta함수 또는 \Q메타 인용 이스케이프 시퀀스를 사용하는 것이 일반적입니다 .

    /$unquoted\Q$quoted\E$unquoted/

\Q와 사이에 리터럴 백 슬래시 (보간 된 변수가 아닌 변수)를 \E넣으면 큰 따옴표 백 슬래시 보간으로 인해 결과가 혼동 될 수 있습니다. 에 리터럴 백 슬래시를 사용해야하는 경우 perlop의“따옴표 붙은 구문 구문 분석에 대한 기본 정보”를\Q...\E 참조하십시오 .

quotemeta그리고 \Q완전히 설명되어 있습니다 quotemeta .


3

grep에 -P 옵션 ( PCRE 를 의미 함) 이있는 경우 다음을 수행 할 수 있습니다.

grep -P "^\Q$1\E"

질문을 참조하고 원하는 경우 PCRE 문서 를 참조하십시오 .


2

사용하지 않는 문자가 있으면이를 사용하여 줄의 시작을 표시 할 수 있습니다. 예를 들어 $'\a'(ASCII 007)입니다. 추악하지만 작동합니다.

{ echo 'this is a line to match'; echo 'but this is not'; } >file.txt

stuffing=$'\a'    # Guaranteed never to appear in your source text
required='this'   # What we want to match that beginning of a line

match=$(sed "s/^/$stuffing/" file.txt | grep -F "$stuffing$required" | sed "s/^$stuffing//")

if [[ -n "$match" ]]
then
    echo "Yay. We have a match: $match"
fi

일치하는 줄이 필요하지 않으면 후행을 삭제하고을 sed사용할 수 있습니다 grep -qF. 그러나 awk(또는 perl)를 사용하면 훨씬 쉽습니다 .


0

루프없이 파일을 찾으려면 다음을 사용할 수 있습니다.
검색 문자열의 길이로 파일을 자릅니다.

  cut -c1-${#1} < file

고정 문자열과 리턴 라인 번호를 찾으십시오.

  grep -Fn "$1" <(cut -c1-${#1} < file)

같은 줄 번호를 사용하십시오 sed -n '3p;11p' file

  sed -n "$(grep -Fn "$1" <(cut -c1-${#1} < file) | sed 's/:.*/p;/' | tr -d '\n')" file

이 줄을 삭제하려면

  sed "$(grep -Fn "$1" <(cut -c1-${#1} < file) | sed 's/:.*/d;/' | tr -d '\n')" file
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.