Changed permalink structure. Need help with redirecting old posts

…it redirected the old URLs to the new URLs without the end trailing slash and then redirected again with the trailing slash. So, it generated 2 redirects instead of one.

RedirectMatch 301 ^/([^/]+)/([0-9]{4})/([0-9]{2})/([^/]+)/$ https://www.example.com/$4

In that case you should simply be able to append a trailing slash to the target URL in the above directive (generated by yoast). ie. /$4/ instead of /$4. The second redirect you are seeing, that appends the trailing slash, is being performed by something else.

For example, the complete directive would be:

RedirectMatch 301 ^/([^/]+)/([0-9]{4})/([0-9]{2})/([^/]+)/$ https://www.example.com/$4/

You will need to clear your browser cache before testing. Preferably test with 302 (temporary) redirects to avoid potential caching issues (ie. change the 301 to 302 in the first argument of the above directive.)


Optimisation

However, the above directive can be simplified. Since you only need to capture the last path segment, you can avoid the parenthesised subpatterns in the regex (2nd argument). For example:

RedirectMatch 301 ^/[^/]+/\d{4}/\d{2}/([^/]+)/$ https://www.example.com/$1/

The \d shorthand character class is the same as [0-9]. Since we are only capturing the postname (4th path segment), we use $1, not $4 in the target URL.


Use mod_rewrite instead

However, the RedirectMatch directive (part of mod_alias) is processed after mod_rewrite (as used by the WordPress code block), so ideally you should be using mod_rewrite here instead in order to avoid unexpected conflicts (and it will be marginally more efficient).

For example, instead of the above RedirectMatch, use the following mod_rewrite RewriteRule directive at the top of your .htaccess file before the # BEGIN WordPress section:

RewriteRule ^[^/]+/\d{4}/\d{2}/([^/]+)/$ https://www.example.com/$1/ [R=301,L]

Just to emphasise, the above RewriteRule directive must go near the top of the .htaccess file, before the WordPress front-controller, otherwise it’s simply never going to get processed. Whereas for the earlier RedirectMatch directive, the ordering does not matter so much (it can appear after the WordPress front-controller) – unless you have other mod_alias Redirect and/or RedirectMatch directives.


UPDATE:

when the original url is accessed without a trailing slash it is not forwarded to the new URL

You can make the trailing slash optional in the above regular expression (regex) by following the slash with ? (0 or 1 occurrences of the preceding element). For example:

RewriteRule ^[^/]+/\d{4}/\d{2}/([^/]+)/?$ https://www.example.com/$1/ [R=301,L]

So now it matches URLs both with and without a trailing slash and redirects to always include a trailing slash.