cut -f1,2,3 -d:"에 대한 대체 인수 대체/확장 대안이 있습니까? 즉, n번째 문자 발생 이후에 트리밍(및 포함)이 있습니까?

cut -f1,2,3 -d:"에 대한 대체 인수 대체/확장 대안이 있습니까? 즉, n번째 문자 발생 이후에 트리밍(및 포함)이 있습니까?

하나고대의initramfs 내부의 버전에서는 ipconfig사용자 입력이 콜론으로 구분된 요소를 최대 7개까지만 제공해야 합니다. 예를 들면 다음과 같습니다.

ip=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf

ipconfig사용자가 7개 이상의 요소를 제공하면 오류가 발생합니다.

따라서 추가(2개의 DNS 확인자)를 잘라야 합니다.

subshell예를 들어 다음과 같이 내부에서 이 작업을 수행할 수 있습니다 cut.

validated_input=$(echo ${user_input} | cut -f1,2,3,4,5,6,7 -d:)

매개변수 확장/대체를 사용하여 cut이와 같은 코드를 어떻게 작성할 수 있습니까?(b)ash

아니요:

  • 서브셸/하위 프로세스 시작(파이프라인)
  • IFS - 인수/파괴

(1) 속도 이후 참조Cut/awk 대신 bash 변수 대체 사용(2) 학습.


즉, n(7번째) 문자 발생을 찾고 거기에서 문자열 끝까지 모든 것을 제거/자르려면 어떻게 해야 합니까?

답변1

이는 매개변수 확장만 사용합니다.

${var%:"${var#*:*:*:*:*:*:*:}"}

:

$ var=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:morefields:another:youwantanother:haveanother:
$ echo "${var%:"${var#*:*:*:*:*:*:*:}"}"
client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf

후행 수정을 제안한 ilkkachu에게 감사드립니다 :!


${parameter#word}
${parameter##word}

파일 이름 확장과 마찬가지로 단어가 확장되어 패턴을 생성합니다(파일 이름 확장자 참조). 패턴이 매개변수 확장 값의 시작과 일치하는 경우 확장 결과는 가장 짧은 일치 패턴("#"의 경우) 또는 가장 긴 일치 패턴("##"의 경우)이 있는 매개변수 확장 값이 됩니다. 제거됨. 매개변수가 "@" 또는 "인 경우'를 사용하면 각 위치 인수에 패턴 제거 작업이 차례로 적용되고 확장이 결과 목록이 됩니다. 매개 변수가 배열 변수인 경우 아래 첨자는 "@" 또는 "'를 실행하면 배열의 각 멤버에 패턴 삭제 작업이 차례로 적용되고 확장이 결과 목록이 됩니다.

이것은 일치를 시도합니다시작매개변수가 있으면 삭제됩니다.

:

$ var=a:b:c:d:e:f:g:h:i
$ echo "${var#a}"
:b:c:d:e:f:g:h:i
$ echo "${var#a:b:}"
c:d:e:f:g:h:i
$ echo "${var#*:*:}"
c:d:e:f:g:h:i
$ echo "${var##*:}"    # Two hashes make it greedy
i

${parameter%word}
${parameter%%word}

파일 이름 확장과 마찬가지로 단어가 확장되어 패턴을 생성합니다. 패턴이 매개변수 확장 값의 후행 부분과 일치하는 경우 확장 결과는 가장 짧은 일치 패턴("%" 케이스) 또는 가장 긴 일치 패턴("%%" 케이스)이 있는 매개변수 값이 제거됩니다. 매개변수가 "@" 또는 "인 경우'를 사용하면 각 위치 인수에 패턴 제거 작업이 차례로 적용되고 확장이 결과 목록이 됩니다. 매개 변수가 배열 변수인 경우 아래 첨자는 "@" 또는 "'를 실행하면 배열의 각 멤버에 패턴 삭제 작업이 차례로 적용되고 확장이 결과 목록이 됩니다.

이것은 일치를 시도합니다매개변수가 있으면 삭제됩니다.

:

$ var=a:b:c:d:e:f:g:h:i
$ echo "${var%i}"
a:b:c:d:e:f:g:h:
$ echo "${var%:h:i}"
a:b:c:d:e:f:g
$ echo "${var%:*:*}"
a:b:c:d:e:f:g
$ echo "${var%%:*}"    # Two %s make it greedy
a

그래서 대답은 다음과 같습니다.

${var%:"${var#*:*:*:*:*:*:*:}"}

${var#...}( 끝에서 제거할 리터럴 문자열(패턴이 아닌)로 처리되도록 주변 따옴표에 유의하십시오 $var.)

적용 대상:

var=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:morefields:another:youwantanother:haveanother:

${var#*:*:*:*:*:*:*:}=morefields:another:youwantanother:haveanother:

내부 확장 ${var%: ... }은 다음과 같습니다.

${var%:morefields:another:youwantanother:haveanother:}

그래서 당신은 나에게 이렇게 말하고 있습니다.

client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:morefields:another:youwantanother:haveanother:

하지만 :morefields:another:youwantanother:haveanother:끝부분을 잘라주세요.

Bash 참조 매뉴얼(3.5.3)

답변2

정규 표현식을 사용하세요:

$ var=a:b:c:d:e:f:g:h:i:j:k:l
$ [[ $var =~ ([^:]*:){6}([^:]*) ]] && echo "${BASH_REMATCH[0]}"
a:b:c:d:e:f:g

이는 표준 셸에서 작동합니다.

#!/bin/sh
var=a:b:c:d:e:f:g:h:i:j:k:l
while true; do 
    case "$var" in
        *:*:*:*:*:*:*:*) var=${var%:*} ;;
        *) break ;;
    esac
done
echo "$var"

IFS또는 기간 설정을 허용하는 경우 read:

$ IFS=: read -a arr <<< "$var"
$ arr=("${arr[@]:0:7}")
$ echo "${arr[@]}"
a b c d e f g
$ printf "%s:%s:%s:%s:%s:%s:%s\n" "${arr[0]}" "${arr[1]}" "${arr[2]}" "${arr[3]}" "${arr[4]}" "${arr[5]}"  "${arr[6]}" 
a:b:c:d:e:f:g

답변3

존재하다 zsh:

$ ip=client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf:x:y:z
$ echo ${(j(:))${"${(@s(:))ip}"[1,7]}}
client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf
  • ${(s(:))var}나뉘다:
  • "${(@)...}": 빈 요소를 유지해야 합니다(예: "$@").
  • ${var[1,7]}요소 1~7
  • ${(j(:))var}요소 추가:

아니면 이렇게 할 수도 있습니다:

$ set -o extendedglob
$ echo ${(M)ip##([^:]#:)(#c0,6)[^:]#}
client-ip:server-ip:gw-ip:netmask:hostname:device:autoconf
  • ${var##pattern}ksh와 마찬가지로 패턴과 일치하는 가장 긴 선행 부분을 제거합니다.
  • (M): 다음으로 확장중간 사이즈부품을 벗기지 말고 고치세요.
  • x#: 0개 이상의 xs (예: regexp *)
  • (#c0,6)0에서 6까지의 이전 원자( ksh와 유사 {x,y}(...))

관련 정보