
내가 찾은 방법은 줄 바꿈에 영향을 주어 줄을 더 나눕니다.
예를 들어...
$ message="First Line\nSecond Line";
$ echo "${message^^}"
FIRST LINE\NSECOND LINE
문자열을 대문자로 변환하되 이스케이프 문자를 유지하여 다음 출력을 얻는 우아한 방법이 있습니까?
FIRST LINE\nSECOND LINE
"\n"을 0001로 변경하거나 변환을 적용한 다음 0001을 "\n"으로 반환하는 등 복잡한 작업을 수행할 수 있습니다. 하지만 더 좋은 방법이 있을 수도 있습니다.
답변1
zsh
대신 사용하십시오 bash
:
$ message="First Line\nSecond Line"
$ set -o extendedglob
$ print -r -- ${message//(#b)((\\?)|(?))/$match[2]$match[3]:u}
FIRST LINE\nSECOND LINE
(또는 해당 문제에 대한 모든 쉘) 에서 bash
GNU 구현을 사용하면 sed
동일한 작업을 수행할 수 있습니다.
$ printf '%s\n' "$message" | sed -E 's/(\\.)|(.)/\1\u\2/g'
FIRST LINE\nSECOND LINE
대체 횟수를 최소화하므로 더 효율적일 수 있는 몇 가지 변형은 다음과 같습니다.
zsh
print -r -- ${message//(#b)((\\?)|([^\\]##))/$match[2]$match[3]:u}
또는
print -r -- ${message//(#b)((\\?)#)([^\\]##)/$match[1]$match[3]:u}
GNU
sed
번역:printf '%s\n' "$message" | sed -E 's/(\\.)|([^\\]+)/\1\U\2/g'
또는
printf '%s\n' "$message" | sed -E 's/((\\.)*)([^\\]+)/\1\U\3/g'
\Mx
(s에서 지원하고 0xf8 바이트('x' + 0x80)로 확장된 이스케이프 시퀀스와 같은 Meta-x)를 (0xd8)로 변환합니다 . 그들은 또한 or 로 변환하지만 동일하게 확장되므로 문제가 되지 않습니다.zsh
print
\MX
\x7a
\x7A
\u007a
\u007A
\Cx
\CX
답변2
나는 이스케이프 시퀀스를 리터럴 문자로 해석하고 싶은 유혹을 받습니다.
message="First Line\nSecond Line"
declare -u Message # uppercase on assignment
printf -v Message -- "${message//%/%%}" # assign
declare -p Message # inspect
결과
declare -u msg="FIRST LINE
SECOND LINE"
답변3
echo "$message" | sed -e 's/^[[:lower:]]/\u&/' -e 's/\([^\]\)\([[:lower:]]\)/\1\u\2/g' \
-e 's/\([^\]\)\([[:lower:]]\)/\1\u\2/g'
-e 's/^[[:lower:]]/\u&/'
문자열의 첫 번째 문자(또는 더 일반적으로 행의 첫 번째 문자)가 소문자인 경우 대문자로 표시합니다. 줄의 첫 번째 문자는 이스케이프할 수 없기 때문입니다. 잘. 이것은 주어진 것입니다.-e 's/\([^\]\)\([[:lower:]]\)/\1\u\2/g'
한 번에 두 문자씩 줄을 봅니다. 소문자 앞에 백슬래시가 없으면 이전 문자는 유지되고 소문자는 대문자로 표시됩니다.이 정도면 전체 라인을 처리하기에 충분하다고 생각할 수도 있습니다. 불행하게도 한 번에 두 문자씩 처리하기 때문에 문자 하나 걸러서만 가져옵니다.
$ echo "first line\nsecond line" | sed -e 's/\([^\]\)\([[:lower:]]\)/\1\u\2/g' fIrSt LiNe\nSeCoNd LiNe
그래서,
-e 's/\([^\]\)\([[:lower:]]\)/\1\u\2/g'
두 번째에도 같은 작업을 수행합니다. 그러면 첫 번째 패스에서 건너뛴 문자가 선택됩니다.
대체 버전:
echo "$message" | sed -e 's/^[[:lower:]]/\u&/' \
-e ': loop; s/\([^\]\)\([[:lower:]]\)/\1\u\2/g; t loop'
기본적으로 첫 번째 버전과 동일하지만 두 번째 버전과 중복되지는 않습니다.s
루프로 반복하는 명령입니다.
불행하게도 이중 백슬래시에서는 제대로 작동하지 않습니다. 대문자여야 하지만 이스케이프 foo\\bar
된 백슬래시이기 때문에 이스케이프가 발생해서는 안 됩니다.FOO\\bAR
b
\\
b
답변4
이 변수는 행별로 반복될 수 있습니다. 그런 다음 출력을 다시 연결하십시오.
큰 타격:
$ message="First Line\nSecond Line";
$ message=$(echo -e ${message} |while read -r line; do echo -n "${line^^}\n" ; done) && message=${message%??}
$ echo ${message}
FIRST LINE\nSECOND LINE