如何用正则、case语句和sed修改Bash日期输出为带序数后缀的格式
Hey there! Let's fix that date formatting issue you're having. Your current date command outputs Friday, May 2, but you need the ordinal suffix (st/nd/rd/th) to get Friday, May 2nd. Below are three solutions using regex, case statements, and sed as required for your assignment:
Method 1: Using Bash Built-in Regular Expressions
We'll extract the day number, use regex to match which suffix it needs, then substitute it back into the original date string:
#!/bin/bash # Get the raw date output raw_date=$(date "%A, %B %d") # Extract the day number, stripping any leading zero day_num=$(echo "$raw_date" | awk '{print $NF}' | sed 's/^0//') # Use regex to determine the correct suffix if [[ $day_num =~ ^(1|21|31)$ ]]; then suffix="st" elif [[ $day_num =~ ^(2|22)$ ]]; then suffix="nd" elif [[ $day_num =~ ^(3|23)$ ]]; then suffix="rd" else suffix="th" fi # Replace the plain day number with the suffixed version formatted_date=$(echo "$raw_date" | sed "s/ $day_num\b/ $day_num$suffix/") echo "$formatted_date"
This script first grabs the raw date, pulls out the day number (removing leading zeros like 02 to 2), then uses regex checks to assign the right suffix. Finally, it replaces the number in the original string with the suffixed version.
Method 2: Using a Case Statement
Case statements are a cleaner alternative to multiple if checks for matching specific values. The logic is similar to the regex method, but more readable for discrete matches:
#!/bin/bash raw_date=$(date "%A, %B %d") day_num=$(echo "$raw_date" | awk '{print $NF}' | sed 's/^0//') # Use case to map day numbers to suffixes case $day_num in 1|21|31) suffix="st" ;; 2|22) suffix="nd" ;; 3|23) suffix="rd" ;; *) suffix="th" ;; esac formatted_date=$(echo "$raw_date" | sed "s/ $day_num\b/ $day_num$suffix/") echo "$formatted_date"
Here, we match exact day numbers (or groups of numbers like 1|21|31) directly in the case block, which makes the suffix assignment straightforward.
Method 3: Using Sed (Pure Sed Processing)
If you want to handle everything in one pipeline without Bash conditionals, sed can do the job with pattern matching and substitution. We'll first strip leading zeros, then apply the correct suffix:
#!/bin/bash date "%A, %B %d" | sed -E ' # Remove leading zero from single-digit days (e.g., 02 → 2) s/ 0([1-9])/ \1/ # Add "st" to 1, 21, 31 s/ (1|21|31)\b/ \1st/ # Add "nd" to 2, 22 s/ (2|22)\b/ \1nd/ # Add "rd" to 3, 23 s/ (3|23)\b/ \1rd/ # Add "th" to all other valid days s/ ([4-9]|1[0-9]|20|2[4-9]|30)\b/ \1th/ '
The -E flag enables extended regex, making the patterns easier to write. We first clean up leading zeros, then sequentially match each category of days and append the correct suffix.
内容的提问来源于stack exchange,提问作者ninja cowgirl

