สลับลำดับขององค์ประกอบที่คั่นด้วยจุดในสตริง


14

ฉันมีสตริงการป้อนข้อมูลเช่น:

arg1.arg2.arg3.arg4.arg5

ผลลัพธ์ที่ฉันต้องการคือ:

arg5.arg4.arg3.arg2.arg1

มันไม่เสมอ 5 arg's อาจเป็น 2 ถึง 10

ฉันจะทำสิ่งนี้ในสคริปต์ทุบตีได้อย่างไร

คำตอบ:


22
  • ใช้การรวมกันของtr+ tac+paste

    $ tr '.' $'\n' <<< 'arg1.arg2.arg3.arg4.arg5' | tac | paste -s -d '.'
    arg5.arg4.arg3.arg2.arg1
  • ถ้าคุณยังชอบทุบตีคุณก็สามารถทำเช่นนี้ได้

    IFS=. read -ra line <<< "arg1.arg2.arg3.arg4."
    let x=${#line[@]}-1; 
    while [ "$x" -ge 0 ]; do 
          echo -n "${line[$x]}."; 
          let x--; 
    done
  • การใช้perl,

    $ echo 'arg1.arg2.arg3.arg4.arg5' | perl -lne 'print join ".", reverse split/\./;'
    arg5.arg4.arg3.arg2.arg1

2
Bah ผมก็แค่จะโพสต์วิธีการแก้ปัญหา Perl :)
ilkkachu

10

หากคุณไม่รังเกียจสิ่งเล็กน้อยpython:

".".join(s.split(".")[::-1])

ตัวอย่าง:

$ python3 -c 's="arg1.arg2.arg3.arg4.arg5"; print(".".join(s.split(".")[::-1]))'
arg5.arg4.arg3.arg2.arg1
  • s.split(".")สร้างรายการที่มี.สตริงย่อยแยกออกจากกัน[::-1]กลับรายการและร่วมส่วนประกอบของรายการตรงกันข้ามกับ".".join().

5

คุณสามารถทำได้ด้วยการsedเรียกใช้ครั้งเดียว:

sed -E 'H;g;:t;s/(.*)(\n)(.*)(\.)(.*)/\1\4\5\2\3/;tt;s/\.(.*)\n/\1./'

ใช้บัฟเฟอร์พักเพื่อรับ newline ชั้นนำในพื้นที่รูปแบบและใช้ในการทำพีชคณิตจนกว่า newline จะไม่ตามมาด้วยจุดใด ๆ ที่จุดที่มันจะลบจุดนำจากพื้นที่รูปแบบและแทนที่บรรทัดใหม่ด้วยจุด
ด้วย BRE และ regex ที่แตกต่างกันเล็กน้อย:

sed 'H
g
:t
s/\(.*\)\(\n\)\(.*\)\(\.\)\(.*\)/\1\4\5\2\3/
tt
s/\(\.\)\(.*\)\n/\2\1/'

หากอินพุตประกอบด้วยมากกว่าหนึ่งบรรทัดและคุณต้องการกลับคำสั่งซื้อในแต่ละบรรทัด:

sed -E 'G;:t;s/(.*)(\.)(.*)(\n)(.*)/\1\4\5\2\3/;tt;s/(.*)\n(\.)(.*)/\3\2\1/'


3

ด้วย zsh:

$ string=arg1.arg2.arg3.arg4.arg5
$ printf '%s\n' ${(j:.:)${(Oas:.:)string}}
arg5.arg4.arg3.arg2.arg1

เพื่อรักษาองค์ประกอบที่ว่างเปล่า:

$ string=arg1.arg2.arg3.arg4..arg5.
$ printf '%s\n' ${(j:.:)"${(@Oas:.:)string}"}
.arg5..arg4.arg3.arg2.arg1
  • s:.:: แยก .
  • Oa: เรียงแถวในสิ่งที่ตรงกันข้ามrray Indice o rder
  • j:.:: .เข้าร่วมใน
  • @: ทำ"$@"เหมือนการขยายตัวเมื่ออยู่ในเครื่องหมายคำพูดคู่ดังนั้นการขยายไม่ได้ถูกลบออกอย่างว่างเปล่า

POSIX (หรือbash) ที่เทียบเท่าอาจเป็นดังนี้:

string=arg1.arg2.arg3.arg4..arg5.

IFS=.; set -f
set -- $string$IFS # split string into "$@" array
unset pass
for i do # reverse "$@" array
  set -- "$i" ${pass+"$@"}
  pass=1
done
printf '%s\n' "$*" # "$*" to join the array elements with the first
                   # character of $IFS

(โปรดทราบว่าzsh(เป็นshอีมูเลชัน) yashและpdkshเชลล์แบบอิงบางตัวไม่ใช่ POSIX ซึ่งถือว่า$IFSเป็นตัวคั่นฟิลด์แทนที่จะเป็นตัวคั่นฟิลด์)

ที่มันแตกต่างจากบางส่วนของการแก้ปัญหาอื่น ๆ ให้ที่นี่เป็นว่ามันไม่ได้รักษาตัวอักษรขึ้นบรรทัดใหม่ (และในกรณีของzsh, NUL หนึ่งอย่างใดอย่างหนึ่ง) เป็นพิเศษที่$'ab.cd\nef.gh'จะย้อนกลับไป$'gh.cd\nef.ab'ไม่ได้หรือ$'cd.ab\ngh.ef'$'gh.ef.cd.ab'


มีอะไรผิดปกติกับIFS="."; set -f; set -- $string$IFS; for i; do rev="$i$IFS$rev"; done; printf '%s\n' "${rev%$IFS}"?

@ BinaryZebra ไม่มีอะไร (นอกเหนือจากfor i; doที่ไม่ใช่ POSIX (ยัง) แม้ว่ามันจะสนับสนุนโดยเชลล์ POSIX ทั้งหมดที่ฉันรู้) เป็นเพียงวิธีการแก้ปัญหานั่นคือการแปลโดยตรงของzshหนึ่ง (แยกเป็นอาร์เรย์อาร์เรย์ย้อนกลับเข้าร่วมองค์ประกอบอาร์เรย์) แต่ใช้ตัวดำเนินการ POSIX เท่านั้น (ฉันเปลี่ยนstring=$string$IFS; set -- $stringไปset -- $string$IFSเป็นเหมือนที่ดูเหมือนว่าจะทำงานอย่างต่อเนื่องทั่วทั้งเปลือกหอยขอบคุณ)
Stéphane Chazelas

2

ฉันเห็นว่าราหุลได้โพสต์วิธีการทุบตีดั้งเดิม (ซึ่งเป็นเวอร์ชั่นอื่น) ซึ่งเป็นเวอร์ชั่นที่สั้นกว่าของเวอร์ชั่นแรกที่ฉันใช้:

function reversedots1() (
  IFS=. read -a array <<<"$1"
  new=${array[-1]}
  for((i=${#array[*]} - 2; i >= 0; i--))
  do
    new=${new}.${array[i]}
  done
  printf '%s\n' "$new"
)

แต่ฉันไม่สามารถหยุดที่นั่นและรู้สึกว่าจำเป็นต้องเขียนโซลูชัน bash-centric แบบเรียกซ้ำ:

function reversedots2() {
  if [[ $1 =~ ^([^.]*)\.(.*)$ ]]
  then
    printf %s $(reversedots2 "${BASH_REMATCH[2]}") . "${BASH_REMATCH[1]}"
  else
    printf %s "$1"
  fi
}


1

Pure Bash ต้องใช้ระยะเวลาต่อท้ายกับอินพุต:

echo 'foo.bar.baz.' | ( while read -d . f;do g="$f${g+.}$g" ;done;echo "$g" )

ใช้printf %s "$g"ถ้าองค์ประกอบประใด ๆ สามารถเริ่มต้นด้วยยัติภังค์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.