ฉันมีสตริงการป้อนข้อมูลเช่น:
arg1.arg2.arg3.arg4.arg5
ผลลัพธ์ที่ฉันต้องการคือ:
arg5.arg4.arg3.arg2.arg1
มันไม่เสมอ 5 arg's อาจเป็น 2 ถึง 10
ฉันจะทำสิ่งนี้ในสคริปต์ทุบตีได้อย่างไร
ฉันมีสตริงการป้อนข้อมูลเช่น:
arg1.arg2.arg3.arg4.arg5
ผลลัพธ์ที่ฉันต้องการคือ:
arg5.arg4.arg3.arg2.arg1
มันไม่เสมอ 5 arg's อาจเป็น 2 ถึง 10
ฉันจะทำสิ่งนี้ในสคริปต์ทุบตีได้อย่างไร
คำตอบ:
ใช้การรวมกันของ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
หากคุณไม่รังเกียจสิ่งเล็กน้อย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()
.
คุณสามารถทำได้ด้วยการ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/'
วิธีการแก้ปัญหา SED:
sed 's/\./\n/g' yourFile | tac | sed ':a; $!{N;ba};s/\n/./g'
ด้วย 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 rderj:.:
: .
เข้าร่วมใน@
: ทำ"$@"
เหมือนการขยายตัวเมื่ออยู่ในเครื่องหมายคำพูดคู่ดังนั้นการขยายไม่ได้ถูกลบออกอย่างว่างเปล่า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}"
?
for i; do
ที่ไม่ใช่ POSIX (ยัง) แม้ว่ามันจะสนับสนุนโดยเชลล์ POSIX ทั้งหมดที่ฉันรู้) เป็นเพียงวิธีการแก้ปัญหานั่นคือการแปลโดยตรงของzsh
หนึ่ง (แยกเป็นอาร์เรย์อาร์เรย์ย้อนกลับเข้าร่วมองค์ประกอบอาร์เรย์) แต่ใช้ตัวดำเนินการ POSIX เท่านั้น (ฉันเปลี่ยนstring=$string$IFS; set -- $string
ไปset -- $string$IFS
เป็นเหมือนที่ดูเหมือนว่าจะทำงานอย่างต่อเนื่องทั่วทั้งเปลือกหอยขอบคุณ)
ฉันเห็นว่าราหุลได้โพสต์วิธีการทุบตีดั้งเดิม (ซึ่งเป็นเวอร์ชั่นอื่น) ซึ่งเป็นเวอร์ชั่นที่สั้นกว่าของเวอร์ชั่นแรกที่ฉันใช้:
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
}
ไม่เห็นawk
คำตอบดังนั้นต่อไปนี้เป็นคำตอบ:
echo 'arg1.arg2.arg3' | awk -F. '{for (i=NF; i>0; --i) printf "%s%s", (i<NF ? "." : ""), $i; printf "\n"}'
Pure Bash ต้องใช้ระยะเวลาต่อท้ายกับอินพุต:
echo 'foo.bar.baz.' | ( while read -d . f;do g="$f${g+.}$g" ;done;echo "$g" )
ใช้printf %s "$g"
ถ้าองค์ประกอบประใด ๆ สามารถเริ่มต้นด้วยยัติภังค์