我对此有一个想法,我们必须使用grep
反向引用,但这是我能得到的最接近的结果
grep "^[a-zA-z]\$[a-zA-z]\
我的问题是我不确定如何检查第一个字符 == 到最后一个字符?
答案1
你需要
grep -E '^([a-zA-Z]).*\1$'
捕获其中的第一个字符(...)
并使用其反向引用作为最后一个字符并跳过 之间的所有其他内容.*
。这-E
开关使能扩展正则表达式匹配,这样我们就不需要在我们的grep
命令范围内逃脱捕获组,但是;您还可以执行以下操作并提高可移植性:
grep '^\([a-zA-Z]\).*\1$'
如果您只想输出包含单个字符的行(但这也称为第一个和最后一个字符相同),您可以选择定义它的存在,请尝试:
grep -- '^\([a-zA-Z]\)\(.*\1\)\{0,1\}$'
\{0,1\}
不匹配或只匹配一次图案 .*\1
多于。
或者在每个上都匹配这个单身的像上面这样的字节字符是:
grep -- '^\(.\)\(.*\1\)\{0,1\}$'
默认情况下grep
使用--basic-regexp
(Basic-Regular-Expression, BRE) 模式匹配,其中元字符如?
, +
, {
, |
, (
, 和)
失去其特殊含义并按字面匹配,要将它们用作正则表达式,我们需要使用转义类型\?
, \+
, \{
,\|
,\(
, 和\)
或 只是切换模式匹配到 ERE -E
(但请注意,POSIX ERE 没有反向引用)。
检查字符串的长度是否相同氮:
grep -- '^\([a-zA-Z]\{N-HERE\}\)\(.*\1\)\{0,1\}$'
像3字符长度:
grep -- '^\([a-zA-Z]\{3\}\)\(.*\1\)\{0,1\}$'
再次,如上所述,这将返回类似的行3(氮一般来说)字符长度xxx
,如果你不需要这些,更改为:
grep -- '^\([a-zA-Z]\{3\}\).*\1$'
答案2
如果处理文本行,awk
是最明显的:
awk 'length>1 && substr($0,1,1)==substr($0,length,1)' file
如果这是一个 shell 变量:
case $var in ''|?) echo no;; "${var#"${var%?}"}"*) echo yes;; *) echo no;; esac
[ "${#var}" -gt 1 ] && [ "${var%"${var#?}"}" = "${var#"${var%?}"}" ]
答案3
当 shell 可以轻松执行测试时,为什么要使用像grep
或 这样的外部实用程序?awk
假设字符串至少包含两个字符 - 如果字符串仅包含一个字符,有人可能会认为最后一个字符等于第一个字符,但我认为OP的问题是关于包含两个或更多字符的字符串。
#!/bin/bash
# set -x
# set -v
is_match() {
(( ${#1} < 2 )) && return 1
[[ "${1:0:1}" != "${1: -1}" ]] && return 1
return 0
}
check() {
if is_match "$1"
then
echo "\"$1\" is a match"
else
echo "\"$1\" is not a match"
fi
}
check ""
check "a?"
check "a*"
check "a"
check "cdc"
check "abbba"
check "é"
check "étéa"
check "été"
输出:
"" is not a match
"a?" is not a match
"a*" is not a match
"a" is not a match
"cdc" is a match
"abbba" is a match
"é" is not a match
"étéa" is not a match
"été" is a match
答案4
将当前记录拆分为空字符串,然后将第一个字段与最后一个字段进行比较
$ echo "racecar" \
| gawk -F "" '$1 == $NF'
racecar
- 请注意,此工件仅适用于
GNU awk
@Ed Morton 所指出的情况。