sed 출력을 printf의 형식화된 인쇄처럼 어떻게 형식화할 수 있습니까?

sed 출력을 printf의 형식화된 인쇄처럼 어떻게 형식화할 수 있습니까?

sed가 텍스트를 printf와 유사한 인쇄용 형식의 문자열로 바꿀 수 있습니까?

다음 sed 명령은 "$domain"의 현재 값으로 시작하는 줄을 변수에 지정된 여러 값으로 바꿉니다.

/bin/sed  "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1\n${domain} ${limittype} ${limititem} ${value}/" /etc/security/limits.conf

그러나 해당 도메인의 길이가 다르기 때문에 출력이 올바르게 정렬되지 않습니다.

그러면 출력은 다음과 같을 것입니다.

#oracle   hard   nproc    131072
oracle hard nproc 666

효과적이긴 하지만 읽기가 어렵습니다. 나는 다음과 같은 것을 얻는 것을 선호합니다

#oracle   hard   nproc    131072
oracle   hard   nproc    666

내가 얻을 수 있는 최상의 결과는 다음과 같습니다.

/bin/sed  "s/\(^${domain}\)\( *\)\(${limittype}\)\( *\)\(${limititem}\)\( *\)\(.*\)/$EXPL#\1\2\3\4\5\6\7\n${domain}\2${limittype}\4${limititem}\6${value}/" /etc/security/limits.conf

하지만 저는 이를 수행하기 위해서는 좀 더 우아한 방법이 있어야 한다고 믿습니다.

이것sed oneliners 문서지정된 수의 문자를 사용하는 몇 가지 예가 포함되어 있습니다.

sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  # set at 78 plus 1 space

그러나 이것은 regexp장 내가 아닌 장 에 있습니다 replacement.

답변1

이론적으로는 이 작업을 sed에서 완전히 수행할 수 있지만(Turing이 완료되었으므로) 작업에 적합한 도구는 아닙니다.

간단한 방법은 sed에 탭 문자를 삽입한 다음 공백으로 후처리하는 것입니다. 모든 열이 어디에 있는지 확인할 수 있으면 sed 출력을 파이프하십시오.expand.

</etc/security/limits.conf \
sed  "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1\n${domain}\t${limittype}\t${limititem}\t${value}/" |
expand -t 10,17,26

\t(Sed가 이를 지원하지 않으면 리터럴 탭을 사용하십시오 \t.)

열 너비를 미리 모른다면 BSD를 사용해보십시오column유용. 전체 입력 파일을 살펴보고 모든 행 길이를 수용하는 열 너비를 결정합니다.

</etc/security/limits.conf \
sed  "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1 ${domain} ${limittype} ${limititem} ${value}/" |
column -t

sed 스크립트가 주석 처리된 줄과 주석 처리되지 않은 줄을 모두 다시 작성하는 경우 또는 를 사용하는 경우 column주석 처리된 줄이 주석 표시의 너비를 왜곡하도록 몇 가지 후처리를 수행해야 합니다.

… | sed '/^#/ s/ //'

대신 awk를 사용할 수 있습니다. 기능 이 있습니다 printf. 추가 보너스로 검색 열 내용 내의 특수 문자(예: 또는 )를 보호하는 쉬운 방법이 있습니다 ..*

</etc/security/limits.conf awk -v domain="$domain" -v limittype="$limittype" -v limititem="$limititem" -v value="$value" '
$1 == domain && $2 == limittype && $3 == limititem  {
    printf "#%-9s %-8s %-9s %s\n%-9s %-8s %-9s %s\n", $1, $2, $3, $4, $1, $2, $3, value; next
}
1 {print}
'

답변2

-r이것은 많은 혼란을 없애는 확장된 정규식 구문을 사용합니다 . 또한 일부 필드 값을 이미 알고 있으므로 실제로 역참조할 필요가 없으므로 혼란과 오버헤드가 줄어듭니다.

&특별한 대체 값입니다. 일치하는 전체 패턴을 저장합니다. &혼란을 줄이려면 ,를 다시 사용하십시오 . 역참조가 아니기 때문에 오버헤드가 크게 줄어듭니다.

나는 입력 필드 사이에 적어도 하나의 공백이 있다고 가정하여 ( +)vs ( *).. 를 사용했습니다 . 사실이 아니라는 +사실로 바꾸십시오 .*

EXPL=
dom=oracle
typ=hard
itm=nproc
val=666

echo "oracle   hard   nproc    131072" |
  sed -r "s/^$dom( +)$typ( +)$itm( +).*/$EXPL#&\n$dom\1$typ\2$itm\3$val/" 

산출

#oracle   hard   nproc    131072
oracle   hard   nproc    666

답변3

sed 출력 형식을 지정하려면 printf를 사용하세요.

printf "%5s %12s %4s\n" $(sed 's/.../.../')

관련 정보