문자열을 라인으로 분할하고 출력 프레임

문자열을 라인으로 분할하고 출력 프레임

나는 문자열을 얻고, 최대 문자 너비를 설정한 다음, 한도에 가깝거나 한도에 있는 줄을 단어별로 분할한 다음, 전체 내용을 구성하는 방법을 연구해 왔습니다.

printf배열과 루프를 사용하여 이 작업을 수행했지만 for짜증납니다. 비록 초보적이지만* 매번 모든 작업을 수행해야 합니다.

여기에 이미지 설명을 입력하세요.

함수를 만들고 문자열을 매개변수로 전달하고 싶습니다. 실제로 이 작업을 수행하는 방법에 대한 예제를 찾았지만 코드를 내 것으로 만들 만큼 충분히 이해하지 못하기 때문에 코드를 사용하는 것이 두렵습니다. 내가 찾은 것이 다음과 같은 매개 변수로 작동하지 않기 때문에 필수입니다. 프로세스 리디렉션과 명령의 조합입니다 fmt. 나는 끝없이 시도했지만 성공하지 못했습니다. 그런 다음 fold의 매뉴얼 페이지에서 찾은 참조를 시도했습니다 .fmt

여기에 있는 문서를 사용하여 파일로 리디렉션한 다음 fmt정리할 수 있다고 생각합니다. 하지만 파일 시스템을 사용하는 printf것은 trap어떻게 해서든지 피하고 싶습니다.

printMESSAGEBOX이것이 내가 얻은 것입니다 . 코드의 함수 입니다 .

#!/usr/bin/env bash

# FORMATING: BOX DRAWING
boxp="                                                                      " ; boxP="                                                                           " ; boxt="      ╭────────────────────────────────────────────────────────────────────────╮" ; boxb="      ╰────────────────────────────────────────────────────────────────────────╯" ; boxT="╭─────────────────────────────────────────────────────────────────────────────╮" ; boxB="╰─────────────────────────────────────────────────────────────────────────────╯" ; boxl="      │ " ; boxL="│ " ; boxr=" │"
# FORMATING: FOREGROUND/TEXT
ñbla () { tput setaf 0;} ; ñred () { tput setaf 1;} ; ñgre () { tput setaf 2;} ; ñyel () { tput setaf 3;} ; ñblu () { tput setaf 4;} ; ñmag () { tput setaf 5;} ; ñcya () { tput setaf 6;} ; ñwhi () { tput setaf 7;}
# FORMATING: BACKGROUND/HIGHLIGHTING
ññbla () { tput setab 0;} ; ññred () { tput setab 1;} ; ññgre () { tput setab 2;} ; ññyel () { tput setab 3;} ; ññblu () { tput setab 4;} ; ññmag () { tput setab 5;} ; ññcya () { tput setab 6;} ; ññwhi () { tput setab 7;}
# FORMATING: MISC (HIGHLIGHT-STANDOUT-ON/HIGHLIGHT-STANDOUT-OFF/RM-STYLE-BOLD-OFF/BOLD-ON/UNDERLINE-ON/UNDERLINE-OFF)
ñH () { tput smso;} ; ñh () { tput rmso;} ; ñ0 () { tput sgr0;} ; alias ñb="ñ0" ; ñB () { tput bold;} ; ñU () { tput smul;} ; ñu () { tput rmul;}
# EXIT CLEANUP
trap ñ0 SIGINT
# MESSAGE PRINTING - REVISED CODE
printBOXHEADER() {
  # SORT OUT INPUT
  while [ "$1" != "" ]; do
    case "$1" in
      --type) shift; type=$1 ;;
      --t0) type=0 ;; # don't print
      --t1) type=1 ;; # green checkmark
      --t2) type=2 ;; # red crossmark
      --t3) type=3 ;; # custom icon
      --t4) type=4 ;; # custom icon, custom color
      --ic) shift; ic=$1 ;;
      --ic-red) ic=red ;; # only obeyed with types 4
      --ic-gre) ic=gre ;; # only obeyed with types 4
      --ic-yel) ic=yel ;; # only obeyed with types 4
      --ic-blu) ic=blu ;; # only obeyed with types 4
      --ic-mag) ic=mag ;; # only obeyed with types 4
      --ic-cya) ic=cya ;; # only obeyed with types 4
      --ic-whi) ic=whi ;; # only obeyed with types 4
      --icon) shift; icon=$1 ;; # single character/emoji, # only obeyed with types 3,4
      --header) shift; header="$1" ;; # optional
    esac
    shift
  done
  # DO THAT THING YOU DO
  if [[ $type -eq 0 ]]; then
    return 0
  elif [[ $type -eq 1 ]]; then
    echo "[$(ñgre) ✔︎ $(ñ0)] $header"
  elif [[ $type -eq 2 ]]; then
    echo "[$(ñred) ✖︎ $(ñ0)] $header"
  elif [[ $type -eq 3 ]]; then
    echo "[ $icon ] $header"
  elif [[ $type -eq 4 ]]; then
    echo "[$(ñ$ic) $icon $(ñ0)] $header"
  fi
}
# MESSAGE PRINTING - HAPHAZARD CODE
msgprint() {
  printf "%s\n" "$boxt"
  for line in "${msg[@]}"; do
    printf "%s%s%s%s\n" "$boxl" "$line" "${boxp:${#line}}" "$boxr"
  done
  printf "%s\n" "$boxb"
}
msgprintw() {
  printf "%s\n" "$boxT"
  for line in "${msg[@]}"; do
    printf "%s%s%s%s\n" "$boxL" "$line" "${boxP:${#line}}" "$boxr"
  done
  printf "%s\n" "$boxB"
}
printMESSAGEBOX() {
  if [[ $widerbox =~ y ]]; then
    msgprintw
  elif [[ $widerbox =~ n ]]; then
    msgprint
  elif [[ $widerbox =~ x ]]; then
    return
  fi
}

widerbox=n
msg=(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do"
    "eiusmod tempor incididunt ut labore et dolore magna aliqua."
    "Pellentesque nec nam aliquam sem et."
)

printBOXHEADER "$@"
printMESSAGEBOX

산출:

zx9:Scripting v$ messageBOXREVISITING 
      ╭────────────────────────────────────────────────────────────────────────╮
      │ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do        │
      │ eiusmod tempor incididunt ut labore et dolore magna aliqua.            │
      │ Pellentesque nec nam aliquam sem et.                                   │
      ╰────────────────────────────────────────────────────────────────────────╯
zx9:Scripting v$ 

printBOXHEADER나는 그것이 처음에는 동일한 지저분한 구조를 갖는 코드의 함수 와 같기를 원합니다 printMESSAGEBOX. 선행 공백은 의도적으로 존재하며, 사용될 때는 정렬되고 printBOXHEADER, 사용되지 않을 때는 주의를 끌기 위해 존재합니다. 적어도 그것이 우리의 의도입니다.

내가 시도한 것 중 하나는 fmt지금까지 사용해 왔던 배열로 행을 분할 하려고 시도한 것입니다 printf. 그러나 전체 문자열을 전달하거나 각 단어를 분할하기 때문에 잘못 인용한 것 같습니다. 또 다른 시도 틀에 박혀 있고 자신의 라인에 맞게 틀에 박혀 있지 않은 것입니다. 거의 다 받았어요... :(

fmt무엇이든 환영하고 높이 평가합니다. 심지어 내 접근 방식에서 완전히 벗어난 경우에도 마찬가지입니다(Bash와 대부분의 시스템에서 일반적으로 사용되는 이전 명령(예: ... [ ]의 항목) 을 사용하여 수행되는 한 )./usr/bin

*: 변명하자면 저는 이제 막 스크립트를 만들기 시작했습니다 :) 하지만 제 실력이 부족하더라도 좋지 않다는 것을 알 수 있습니다.

답변1

당신은 재발명을 하고 있는 것 같아요상자, 대부분의 Linux 배포판(예: debian, ubuntu 등)용으로 apt-get install boxes패키지되어 있습니다.

텍스트를 입력할 수 있습니다 fmt(또는 더 나은 방법은기준)를 입력한 다음 를 입력합니다 boxes.

$ par -w 65 < /tmp/lorem | boxes -d stone 
+----------------------------------------------------------------+
| Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed   |
| do eiusmod tempor incididunt ut labore et dolore magna aliqua. |
| Pellentesque nec nam aliquam sem et.                           |
+----------------------------------------------------------------+

참고: boxes멀티바이트 문자는 현재 구성 파일에서 지원되지 않습니다.github 문제 #72. 사용할 수 있는 아름다운 유니코드 선 그리기 문자가 많기 때문에 이는 불행한 일입니다. 이 문제가 결국 해결되기를 바랍니다.

boxes그러나 입력 텍스트는 멀티바이트 입력 문자를 지원합니다. 및 ANSI 이스케이프 시퀀스(예: 색상). 그러나 지원되지 fmt도 않고 제대로 지원 되지도 않습니다 par. 두 절차 모두 가정합니다.1문자 = 1바이트.

~에 따르면위키피디아 표준 페이지그리고 1.53폴 패치입니다.Par에 멀티바이트 문자 지원 추가, 멀티바이트 패치가 있지만 par아직 업스트림 코드에 병합되지 않았으므로 직접 패치하고 다시 빌드해야 할 수도 있습니다.

답변2

영감이 왔을 때 다른 스크립트를 새로 고치는 방법으로 전환했는데 mapfile이는 정말 간단합니다.

파일을 배열로 리디렉션합니다.

mapfile -t <arbitratyNameForArray> < filename.txt

그러나 같은 일이 또 일어났습니다. 그것은 파일을 받아들이고 변수나 무언가를 즉석에서 주입하고 싶습니다.

독서배쉬 참조 매뉴얼, 매우 도움이 되는쉘체크 위키, 링크가 사라진 임의의 웹사이트 등 드디어 얻었습니다.

리디렉션이 무엇인지, 대체가 무엇인지 더 잘 식별해야 합니다. 특히 여기서는 다음과 같습니다.

mapfile -t <arbitratyNameForArray> < <(some process)

ShellCheck Wiki에 답이 있습니다. 실제로는 두 가지가 있습니다. 하지만 저는 여전히 제가 이해하고 생각해 냈는지 확인하기 위해 뭔가를 하려고 노력했습니다.

msg="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pellentesque nec nam aliquam sem et. Nisi vitae suscipit tellus mauris a diam maecenas sed enim. Sodales ut etiam sit amet nisl purus. Fermentum posuere urna nec tincidunt praesent. Velit dignissim sodales ut eu sem integer vitae justo. Justo donec enim diam vulputate ut pharetra sit amet."

arrayDone=()
while IFS='' read -r line; do
  arrayDone+=("$line")
done < <(fmt -w 76 <(echo "$msg"))


for arrayLine in "${arrayDone[@]}"; do
  printf "%s%s%s\n" "⚡️" "$arrayLine" "↩️"
done

산출:

zx9:Scripting v$ fmtter
⚡️Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod↩️
⚡️tempor incididunt ut labore et dolore magna aliqua. Pellentesque nec nam↩️
⚡️aliquam sem et. Nisi vitae suscipit tellus mauris a diam maecenas sed enim.↩️
⚡️Sodales ut etiam sit amet nisl purus. Fermentum posuere urna nec tincidunt↩️
⚡️praesent. Velit dignissim sodales ut eu sem integer vitae justo. Justo donec↩️
⚡️enim diam vulputate ut pharetra sit amet.↩️
zx9:Scripting v$ 

이제 이것을 실제 코드에 적용해야 합니다.

어떻게 작동하나요?

첫째, arrayDone=()배열을 사용하기 전에 간단히 배열을 선언합니다. while IFS='' read -r line; do arrayDone+=("$line") done; while루프 obvi를 시작하여 IFS=''단어 구분 기호로 공백 문자를 제거합니다. 끝없이 읽어야 하는 내용은 서브쉘에서만 수행되거나 일부 격리를 사용해야 합니다. 그렇지 않으면 혼란이 발생할 것입니다... 어떤 생각이 있습니까? 제가 말한건 다 잊어버리세요, 제가 설명을 잘 못해서 여기에 있는 문서와 비교해보려고 낙서를 하고 + 파일로 리다이렉트를 했더니 이해가 더 쉽네요. 여기서 나를 도와준 많은 사람들처럼 적어도 한 사람이라도 도움을 줄 수 있었으면 좋겠습니다. :)

감사해요!

Bash 스크립트: 문자열을 여러 줄로 나누고 배열에 추가

관련 정보