捕获组与非捕获组概念:https://segmentfault.com/a/1190000021043947
文章中的工具用的正则表达式公式: https://regex101.com/
非捕获部分:(?:.*?<span title="(.*?)" .*?<\/span>)?




对天气中的温度和风力有时间只有一个温度和风力的情况的判断算法:
温度部分:
    $temperature = '';
    if (preg_match('/<span>(.*?)<\/span>\/<i>(.*?)<\/i>/', $matches[4], $temp_matches)) {
        $temperature = $temp_matches[1] . '/' . $temp_matches[2];
    } else if (preg_match('/<i>(.*?)<\/i>/', $matches[4], $temp_matches)) {
        $temperature = $temp_matches[1];
    }

风力部分:
问ChatGPT:我只想知道正则如何匹配到下面这段的:

<p class="win">
<em>
<span title="南风" class="S"></span>
<span title="南风" class="S"></span>
</em>
<i>&lt;3级</i>
</p>
对下面这段正则作下解释:

<p class="win">.*?<span title="(.*?)" .*?<\/span>(?:.*?<span title="(.*?)" .*?<\/span>)?
上面第一个.*?是非贪婪匹配它后面的:<span title=。
上在第二个(.*?)是匹配南风。
上在第三个.*?是非贪婪匹配它后面的:<\/span>。
是对的吧?
二、最想知道的是:
(?:.?<span title="(.?)" .?</span>)?
上在这段正则里面的:?:.? 是想干嘛的呢?
它最后的问号是用来匹配0次或1次用的,这个是这么理解吧。

ChatGPT回答如下:
你说得基本是对的。让我逐步解释一下你提到的正则表达式是如何匹配 `<p class="win">` 这段 HTML 代码的,以及 `(?:.*?<span title="(.*?)" .*?<\/span>)?` 这部分正则表达式的具体作用。

### 1. 正则表达式整体

```regex
<p class="win">.*?<span title="(.*?)" .*?<\/span>(?:.*?<span title="(.*?)" .*?<\/span>)?
```

#### 1.1. `<p class="win">.*?<span title="(.*?)" .*?<\/span>`

- `<p class="win">`: 匹配 `<p>` 标签的开头部分,class 属性为 `win`。
- `.*?`: 非贪婪模式匹配任意字符,尽量少的字符,直到遇到 `<span title=`。
- `<span title="(.*?)"`: 匹配第一个 `span` 标签,并捕获 `title` 属性的值。`(.*?)` 是一个非贪婪模式的捕获组,匹配 `title` 属性的内容,这里会匹配到 `南风`。
- ` .*?<\/span>`: 非贪婪模式匹配任意字符,直到遇到 `</span>`。

这一部分的正则表达式解释如下:
- `<p class="win">` 精确匹配标签的开始部分。
- `.*?` 尽量少的匹配任意字符,直到遇到 `<span title=`。
- `<span title="(.*?)"` 匹配 `span` 标签的 `title` 属性,捕获组 `(.*?)` 非贪婪模式匹配 `title` 的内容,即 `南风`。
- ` .*?<\/span>` 匹配从 `title` 属性结束到 `</span>` 标签结束的所有字符。

#### 1.2. `(?:.*?<span title="(.*?)" .*?<\/span>)?`

- `(?: ... )`: 非捕获组,匹配括号内的内容,但不捕获它。
- `.*?`: 非贪婪模式匹配任意字符,尽量少的字符,直到遇到 `<span title=`。
- `<span title="(.*?)"`: 匹配第二个 `span` 标签,并捕获 `title` 属性的值。`(.*?)` 是一个非贪婪模式的捕获组,匹配 `title` 属性的内容,这里会匹配到第二个 `南风`。
- ` .*?<\/span>`: 非贪婪模式匹配任意字符,直到遇到 `</span>`。
- `?`: 匹配前面的非捕获组 0 次或 1 次。即这部分是可选的。

这一部分的正则表达式解释如下:
- `(?: ... )` 表示一个非捕获组,不会保存匹配结果。
- `.*?` 尽量少的匹配任意字符,直到遇到 `<span title=`。
- `<span title="(.*?)"` 匹配 `span` 标签的 `title` 属性,捕获组 `(.*?)` 非贪婪模式匹配 `title` 的内容,即第二个 `南风`。
- ` .*?<\/span>` 匹配从 `title` 属性结束到 `</span>` 标签结束的所有字符。
- `?` 表示这个非捕获组是可选的,可以匹配 0 次或 1 次。

### 2. 匹配示例

以你提供的 HTML 代码为例:

```html
<p class="win">
<em>
<span title="南风" class="S"></span>
<span title="南风" class="S"></span>
</em>
<i>&lt;3级</i>
</p>
```

- `<p class="win">`: 匹配 `<p class="win">`。
- `.*?`: 非贪婪模式匹配任意字符,直到遇到 `<span title=`。匹配到 `\n<em>\n`。
- `<span title="(.*?)"`: 匹配 `<span title="南风"` 并捕获 `title` 属性的值 `南风`。
- ` .*?<\/span>`: 匹配 `class="S"></span>\n`。

接下来是可选部分:

- `(?:.*?<span title="(.*?)" .*?<\/span>)?`:
  - `.*?`: 非贪婪模式匹配任意字符,直到遇到 `<span title=`。匹配到 `\n`。
  - `<span title="(.*?)"`: 匹配 `<span title="南风"` 并捕获 `title` 属性的值 `南风`。
  - ` .*?<\/span>`: 匹配 `class="S"></span>\n`。
  - `?`: 表示这个部分是可选的,可以匹配 0 次或 1 次。这次匹配到 1 次。

### 总结

- `<p class="win">.*?<span title="(.*?)" .*?<\/span>`: 匹配 `<p class="win">` 开始标签,直到第一个 `span` 标签的 `title` 属性,并捕获其值。
- `(?:.*?<span title="(.*?)" .*?<\/span>)?`: 匹配从第一个 `span` 标签结束到第二个 `span` 标签结束的内容,并捕获第二个 `span` 标签的 `title` 属性,整个部分是可选的。
- `?` 表示前面的非捕获组是可选的,可以出现 0 次或 1 次。



再对正则知识点细节性问:
(?: ... ) 表示一个非捕获组,不会保存匹配结果。
上面这个是什么意思,请再接合解释下面正则:
(?:.?<span title="(.?)" .*?</span>)?

ChatGPT回答:
好的,让我们详细解释一下 `(?: ... )` 和具体的正则表达式 `(?:.*?<span title="(.*?)" .*?<\/span>)?`。

### 非捕获组 `(?: ... )`

- `(?: ... )` 是一个**非捕获组**,它的作用是将括号内的内容进行分组,但不保存这个组的匹配结果。这和普通的捕获组 `(...)` 不同,普通捕获组会保存匹配结果供后续引用,而非捕获组则不会保存。
- 非捕获组主要用于在需要进行分组但不希望保存匹配结果的情况下,这样可以节省内存,并且在使用正则表达式时不需要担心额外的捕获组会影响捕获组编号。

### 具体的正则表达式 `(?:.*?<span title="(.*?)" .*?<\/span>)?`

#### 分解解释

1. **`(?: ... )`**:
   - 这是一个非捕获组,括号内的内容会被当作一个整体来处理,但不会保存匹配结果。

2. **`.*?`**:
   - 非贪婪模式匹配任意字符,尽量少的字符,直到遇到 `<span title=`。
   - 这里匹配的是从 `<p class="win">` 到第一个 `<span title="...">` 之间的任意字符,包括换行符等。

3. **`<span title="(.*?)"`**:
   - 匹配 `<span title="` 字符串,并捕获 `title` 属性的值。
   - `(.*?)` 是一个非贪婪模式的捕获组,匹配 `title` 属性的内容。例如,`南风`。

4. **` .*?<\/span>`**:
   - 非贪婪模式匹配任意字符,直到遇到 `</span>`。
   - 这里匹配的是从 `title` 属性结束到 `</span>` 标签结束的所有字符。

5. **`(?: ... )?`**:
   - 问号 `?` 表示前面的非捕获组是可选的,可以匹配 0 次或 1 次。
   - 整个非捕获组 `(?: ... )` 是可选的,意味着可以有一个额外的 `span` 标签,或者没有。

#### 具体示例

以你的 HTML 代码为例:

```html
<p class="win">
<em>
<span title="南风" class="S"></span>
<span title="南风" class="S"></span>
</em>
<i>&lt;3级</i>
</p>
```

匹配过程如下:

1. **第一部分** `<p class="win">.*?<span title="(.*?)" .*?<\/span>`:
   - 匹配 `<p class="win">` 开始标签。
   - `.*?` 非贪婪模式匹配任意字符,直到遇到第一个 `<span title=`。
   - 匹配并捕获第一个 `span` 标签的 `title` 属性值 `南风`。
   - 匹配 `</span>` 标签。

2. **第二部分** `(?:.*?<span title="(.*?)" .*?<\/span>)?`:
   - `(?: ... )` 非捕获组,将内容作为整体处理。
   - `.*?` 非贪婪模式匹配任意字符,直到遇到第二个 `<span title=`。
   - 匹配并捕获第二个 `span` 标签的 `title` 属性值 `南风`。
   - 匹配 `</span>` 标签。
   - `?` 表示非捕获组是可选的,可以匹配 0 次或 1 次。

### 完整正则表达式的匹配过程

完整的正则表达式 `(?:.*?<span title="(.*?)" .*?<\/span>)?` 在匹配过程中的作用如下:

1. 从 `<p class="win">` 开始,匹配任意字符直到第一个 `<span title=`。
2. 捕获第一个 `span` 标签的 `title` 属性值。
3. 匹配 `</span>` 标签。
4. 非捕获组 `(?: ... )?` 的内容(可选):
   - 匹配任意字符直到第二个 `<span title=`。
   - 捕获第二个 `span` 标签的 `title` 属性值。
   - 匹配 `</span>` 标签。

这段正则表达式会成功匹配以下内容,并分别捕获两个 `span` 标签的 `title` 属性值:

```html
<p class="win">
<em>
<span title="南风" class="S"></span>
<span title="南风" class="S"></span>
</em>
<i>&lt;3级</i>
</p>
```

结果是捕获两个 `span` 标签的 `title` 属性值 `南风` 和 `南风`。如果只有一个 `span` 标签,那么也能成功匹配,只会捕获第一个 `title` 属性值。


$date = microtime(true);// 返回浮点数,小数点前面是当前时间的时间戳,小数点后为当前时间的微秒
var_dump($date);
// 输出:float(1566897763.0927)



PHP的round函数用于四舍五入浮点数。它的作用是返回最接近一个数字的整数,也可以指定小数点后的位数。例如:

$float = 3.14159;
$rounded = round($float, 2); // 返回 3.14
$rounded = round($float); // 返回 3


要求:timestamp 时间戳 :"timestamp": "1709986011923"        #13位的毫秒数,时间戳(精确到毫秒),当前时间5分钟内请求有效
实现:
cat sendmsg_2.php

php sendmsg_2.php
1709986816.8926         #获取当前Unix时间戳,包括微秒  
1709986816893            #转换为毫秒

问题:
php的这段代码,不支持访问http时redirect到https,如:
访问:http://jtgl.beijing.gov.cn/jgj/lszt/659722/660341/index.html
307 Temporary Redirect导到:https://jtgl.beijing.gov.cn/jgj/lszt/659722/660341/index.html

请将该函数修改成能自动导到https并获取到相应body内容:
//发起https的get请求
function https_get($url,$timeout=120){
   $curl = curl_init();
   curl_setopt($curl, CURLOPT_URL, $url);
   curl_setopt($curl, CURLOPT_HEADER, 0);
   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($curl, CURLOPT_TIMEOUT,$timeout);
   curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);  // 跳过检查                                                                                                                  
   curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);  // 跳过检查                                                                                                                  
   $res = curl_exec($curl);                                                                                                                                                          
   curl_close($curl);                                                                                                                                                                
   return $res;   //返回json对象                                                                                                                                                    
}  

回答:
要在PHP中自动将HTTP请求重定向到HTTPS并获取响应内容,您可以使用curl来检测HTTP响应头中的重定向,然后执行相应的HTTPS请求。以下是修改后的函数示例:

function https_get($url, $timeout = 120) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HEADER, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // 启用重定向跟随

    $response = curl_exec($curl);

    $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    if ($httpCode == 301 || $httpCode == 302) {
        $matches = array();
        preg_match('/Location:(.*?)\n/', $response, $matches);
        $newUrl = trim(array_pop($matches));

        if (!empty($newUrl)) {
            curl_setopt($curl, CURLOPT_URL, $newUrl);
            $response = curl_exec($curl);
        }
    }

    curl_close($curl);
    return $response;
}

$url = "http://jtgl.beijing.gov.cn/jgj/lszt/659722/660341/index.html";
$response = https_get($url);
echo $response;


php -a 测试是OK的。




问题二:那直接在shell下用curl命令实现上面307的Location转向获取到转向后的内容,用什么参数实现呢?我记得好像是有相应参数的。
是的,您可以使用`curl`命令行工具来获取重定向后的内容。要实现HTTP 307重定向的自动跟随,您可以使用`-L`或`--location`参数,这会让`curl`自动跟随重定向并获取最终的内容。下面是示例:


使用`-L`参数,`curl`将自动处理HTTP 307 Temporary Redirect,并获取最终的内容。

3XX response code


       -L, --location
              (HTTP) If the server reports that the requested page has moved to a different location (indicated with a Location: header and a 3XX response code), this option will make
              curl redo the request on the new place. If used together with -i, --include or -I, --head, headers from all requested pages will be shown. When authentication is used, curl
              only sends its credentials to the initial host. If a redirect takes curl to a different host, it will not be able to intercept the user+password. See also --location-
              trusted on how to change this. You can limit the amount of redirects to follow by using the --max-redirs option.
import cycle not allowed
而且如果项目很大的时候,一个包下面有很多 .go 文件,只提示包与包的循环引用(如上图),是很难定位到哪个 .go 文件和哪个 .go 文件直接进行了循环引用,难以排查。

go-cyclic run --dir  ~/go_learning/src/pdfwatcher.src.cctv.cn
Failed. 1 circular dependence chains were found.

┌---→  /Users/jackXiang/go_learning/src/pdfwatcher.src.cctv.cn/Requests/Request.go
┆                                       ↓
└---     /Users/jackXiang/go_learning/src/pdfwatcher.src.cctv.cn/Loger/Loger.go


安装:
go install github.com/elza2/go-cyclic@latest
go: downloading github.com/elza2/go-cyclic v1.1.0
go: downloading github.com/fatih/color v1.15.0
go: downloading golang.org/x/mod v0.8.0
go: downloading github.com/urfave/cli/v2 v2.24.4
go: downloading github.com/mattn/go-isatty v0.0.17
go: downloading github.com/mattn/go-colorable v0.1.13
go: downloading golang.org/x/sys v0.6.0
go: downloading github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.2
go: downloading github.com/russross/blackfriday/v2 v2.1.0



来自:https://link.zhihu.com/?target=https%3A//github.com/elza2/go-cyclic
Windows上用curl -d"" 上传的编码是:EUC-CN
curl -d"向东阳 向守仁"  XXX.XXXX.com
EUC-CN




来自:https://blog.csdn.net/wuxianbing2012/article/details/79727259
Mac系统 解决 python: No such file or directory
ln -s -f /usr/local/bin/python3.9 /usr/local/bin/python      
python  #无法解决
zsh: no such file or directory: /usr/local/Cellar/python@3.9/3.9.13_3/bin/python3.9 #在PATH里面有上面的软链接,但还是指向这个最新的py地址
/usr/local/bin/runlike       #得把它加到环境变量中去没用,还是指向上面最新的。
which python
python: aliased to /usr/local/Cellar/python@3.9/3.9.13_3/bin/python3.9  #aliased指向了最新的
果然如此,vim ~/.zshrc:
alias python="/usr/local/Cellar/python@3.9/3.9.13_3/bin/python3.9"
alias pip="/usr/local/Cellar/python@3.9/3.9.13_3/bin/pip3.9"
alias pip3="/usr/local/Cellar/python@3.8/3.8.9/bin/pip3.8"
alias pip3.8="/usr/local/Cellar/python@3.8/3.8.9/bin/pip3.8"
alias pip3.9="/usr/local/Cellar/python@3.9/3.9.13_3/bin/pip3.9"

修改为就好了:
alias python="/usr/local/Cellar/python@3.9/3.9.14/bin/python3.9"
alias pip="/usr/local/Cellar/python@3.9/3.9.14/bin/pip3.9"
alias pip3="/usr/local/Cellar/python@3.9/3.9.14/bin/pip3.9"
alias pip3.8="/usr/local/Cellar/python@3.9/3.9.14/bin/pip3.9"
alias pip3.9="/usr/local/Cellar/python@3.9/3.9.14/bin/pip3.9"

ls /usr/local/Cellar/python@3.9/3.9.13_3/bin/python3.9
ls: /usr/local/Cellar/python@3.9/3.9.13_3/bin/python3.9: No such file or directory #因升级更新Mac新版本系统后没有了。

位置:/usr/bin   sudo cp -rf python3 python
cp: python: Operation not permitted

ln -s  /usr/bin/python3 /usr/bin/python
ln: /usr/bin/python: Operation not permitted





原因:系统保护机制
Disabling SIP
It's also possible to disable System Integrity Protection, but it's generally best to leave it on and do customization in more appropriate locations.
https://stackoverflow.com/questions/36730549/cannot-create-a-symlink-inside-of-usr-bin-even-as-sudo

Restart the system -> long press cmd + R.  select a terminal from utilities menu type the following command csrutil disable close terminal and restart system.

来自:https://stackoverflow.com/questions/36730549/cannot-create-a-symlink-inside-of-usr-bin-even-as-sudo

MAC /usr/bin/目录下 Operation not permitted的解决
mac系统下的Rootless机制,让我们在root权限下也不能随心所欲的读写所有路径了,特殊情况下我们需要关闭Rootless时,可尝试如下操作:
1. 重启按住 Command+R,进入恢复模式,打开Terminal。
2. 键入命令 csrutil disable
3. reboot
Rootless机制是对抗恶意程序的最后防线,除非特殊需要时我们才将其关闭,否则保持开启状态
csrutil enable

原文链接:https://blog.csdn.net/king457757706/article/details/70671250
cat short-if.go


go build short-if.go  
./short-if
1
SpaceX

./short-if
2
Virgin Galactic

./short-if
0
Space Adventures


如果不加:
        rand.Seed(time.Now().Unix())

其值一直是:2

原因是:https://blog.csdn.net/weixin_33816821/article/details/94581126


Go语言的switch语法学习之num的简短声明也可用于switch语句的一部分:


./short-switch
Virgin Galactic

./short-switch  
Random spaceline # 4


cat scope-rules.go   #几月有多少天的一个判断:



./scope-rules
AD 2018 10 24


        default:
            day := rand.Intn(31) + 1
            fmt.Println(era, year, month, day)
        }
        fmt.Println(month,day)  //作用域不再有了。
go build scope-rules.go      
# command-line-arguments
./scope-rules.go:22:14: undefined: month
./scope-rules.go:22:20: undefined: day


包括switch的每个case也是都拥有自己独立的作用域,每个分支里面的day变量在分支结束后,day变量将不再处于作用域之内,switch分支的作用域是唯一一种无需使用大括号标识的作用域。


cat random-date.go



#./random-date
AD 2018 11 30

#./random-date
AD 2018 11 30


研究下闰年:
cat random-date-study.go


./random-date-study
AD 2000 2 18
AD 2000 2 4
AD 2000 2 6
AD 2000 2 8
AD 2000 2 7
AD 2000 2 21
AD 2000 2 7
AD 2000 2 29
AD 2000 2 12
AD 2000 2 12
curl -v -d'1)杰克。
2)杰克\r\n3)杰克东
3)你是谁 "a" "b"
                 [空行的空格全是下划]
4)jack    ' x.xxxx.com


来自:https://blog.csdn.net/zhaozhi406/article/details/11131971
https://www.xknote.com/blog/1127037.html


在Centos8环境中配置PHP出现如上报错:
 
原因是没有安装配置oniguruma导致的 
解决方法如下:
1、获取源码,2.并解压

wget https://github.com/kkos/oniguruma/archive/v6.9.4.tar.gz -O oniguruma-6.9.4.tar.gz
tar -zxf oniguruma-6.9.4.tar.gz
cd oniguruma-6.9.4
备用下载: http://down.24kplus.com/linux/oniguruma/oniguruma-6.9.4.tar.gz

3、编译安装

./autogen.sh && ./configure --prefix=/usr
make && make install
如果是Centos7环境中的话:
 解决方法如下:

yum -y install http://mirror.centos.org/centos-7/7.7.1908/cloud/x86_64/openstack-queens/oniguruma-6.7.0-1.el7.x86_64.rpm
yum -y install http://mirror.centos.org/centos-7/7.7.1908/cloud/x86_64/openstack-queens/oniguruma-devel-6.7.0-1.el7.x86_64.rpm
备用下载:

oniguruma:http://down.24kplus.com/linux/oniguruma/oniguruma-6.7.0-1.el7.x86_64.rpm
oniguruma-devel:http://down.24kplus.com/linux/oniguruma/oniguruma-devel-6.7.0-1.el7.x86_64.rpm
————————————————
版权声明:本文为CSDN博主「薄凉小伙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Kangshuo2471781030/article/details/107241779



python excelsearchKeyList.py k.txt
sys.argv[0] = excelsearchKeyList.py
sys.argv[1] = k.txt

二)判断字符为空:


python excelsearchKeyList.py  k.txt
原创视频
line is null
line is null



三)判断是否传入新的参数:


来自:https://blog.csdn.net/index20001/article/details/74294945#:~:text=Python%E7%A8%8B%E5%BA%8F%E6%9C%89%E4%B8%A4%E7%A7%8D,%E8%A7%A3%E9%87%8A%E5%99%A8%E5%B0%86%E4%BC%9A%E9%80%80%E5%87%BA%E3%80%82
背景:有一篇朋友圈说是一个k8s里面Server的Pod销毁上报Zookeeper出现IP地址连接还是原来的,用到了zk的watcher,理论上不应该这样,于是查来查去,其大体意思就是说用了Go的多进程,有一个进程去读取配置了,因为配置还是老的,而用到了Go的多进程,于是文末那代码,我看了下,简单,但不明白,于是顺藤摸瓜学习一下这个rsync的原理。


——————————
#tree  -L 2 .|grep go
├── loop.go
├── pipe.go
├── waitgrouppointer.go
└── wg.go


#cat loop.go
package main

import (
    "fmt"
    //"time"
)

func main(){
    for i := 0; i < 100 ; i++{
        go fmt.Println(i)
    }
    //time.Sleep(time.Second)
}

这个说是运行太快,子进程没输出主进程就退了,啥也不输出。



#cat pipe.go
package main

import (
    "fmt"
    //"time"
)
func main() {
    c := make(chan bool, 100)
    for i := 0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
            c <- true
        }(i)
    }

    for i := 0; i < 100; i++ {
        <-c
    }
}

这个说是管道要是上万,会耗尽系统管道资源。


#cat waitgroup.go      
package main

import (
    "fmt"
    "sync"
    //"time"
)
func main() {
    wg := sync.WaitGroup{}
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
            wg.Done()
        }(i)
    }
    wg.Wait()
}


这个说是挺好的,因为它用到了原子加减法,这里好像C语言也有类似的函数,



再就是说它是用来阻塞方进程的,WaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为n ,Done() 每次把计数器-1 ,wait() 会阻塞代码的运行,直到计数器地值减为0。

这里首先把wg 计数设置为100, 每个for循环运行完毕都把计数器减一,主函数中使用Wait() 一直阻塞,直到wg为零——也就是所有的100个for循环都运行完毕。相对于使用管道来说,WaitGroup 轻巧了许多。


最后,如果要搞裂成函数,得用引用传入,指针变量:
WaitGroup对象不是一个引用类型
WaitGroup对象不是一个引用类型,在通过函数传值的时候需要使用地址:

#cat waitgrouppointer.go
package main

import (
    "fmt"
    "sync"
    //"time"
)
func main() {
    wg := sync.WaitGroup{}
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go f(i, &wg)
    }
    wg.Wait()
}

// 一定要通过指针传值,不然进程会进入死锁状态
func f(i int, wg *sync.WaitGroup) {
    fmt.Println(i)
    wg.Done()
}


以上来自:https://blog.csdn.net/u013474436/article/details/88749749

溯源来自:https://mp.weixin.qq.com/s/s9G6yDqfeFepbKT6DJASng



#cat wg.go
package main


import (
  "fmt"
  "sync"
)


func main() {
  ok := true
  for i := 0; i <1000; i ++ {
    var arr []int
    wg := sync.WaitGroup{}


    for j := 0; j <2; j ++ {
      wg.Add(1)


      go func() {
        defer wg.Done()
        arr = append(arr, i)
      }()
    }
    wg.Wait()


    if len(arr) < 2 {
      fmt.Printf("error:%d \n", i)
      ok = false
      break
    }
  }


  if ok {
    fmt.Println("ok")
  }
}

阅读全文
Server:echoServer.go


Client:echoClient.go


jackXiang@localhost  ~/golearning  ./echoClient
jack
read from socket:
jack
xiang
read from socket:
xiang

Q:果然Ok,两个问题探讨下:
1)        ip4 := net.ParseIP(ADDR).To4()
        sa := &syscall.SockaddrInet4{Port: PORT}
        copy(sa.Addr[:], ip4)  #这个sa.Addr[:] 冒号啥写法呢?

2)for { 这里面是epoll 吗?}

A:
1.
copy(sa.Addr[:], ip4)  #这个sa.Addr[:] 冒号啥写法呢?

sa.Addr 是一个数组,
sa.Addr[:] 将这个数组临时转为切片,底层数组指向sa.Addr数组
方便copy进行切片复制

2. 就是个for{}死循环,防止代码往下执行

来自:
https://mp.weixin.qq.com/s/dRADQ5kUCT80dX7oEAAXyA
https://mp.weixin.qq.com/s/kFHw73w_IIqjKeicesCpZw
验证器:
https://www.bookstack.cn/read/easyswoole-3.x-zh/Components-validate.md
App/HttpController/Index.php



App/HttpController/BaseController.php



统一验证:
class Index  extends BaseController
{
    function index()
    {
        $this->response()->write("123");
    }

  /**
     * 验证
     *
     * {@inheritdoc}
     * @see \App\HttpController\Index\Index::validateRule()
     */
    protected function validateRule(?string $action): ?Validate
    {
        $v = new Validate();
        $params = $this->request()->getRequestParam();
        echo "Here:\n";
        var_dump($action);
        switch ($action) {
            case 'index':
                {
                    $v->addColumn('title', '竞赛标题')
                        ->required('不能为空')
                        ->notEmpty();
                    $v->addColumn('limit', '每页条数')
                        ->integer();
                    $v->addColumn('page', '当前页码')
                        ->integer();
                    if (isset($params['recommend_status'])) {
                        $v->addColumn('recommend_status', '推荐状态')->integer();
                    }
                    if (isset($params['act_status'])) {
                        $v->addColumn('act_status', '活动状态')->integer();
                    }
                    break;
                }
            case 'searchActivity':
                {
                    $v->addColumn('title', '竞赛标题')
                        ->required('不能为空')
                        ->notEmpty();
                    $v->addColumn('limit', '每页条数')
                        ->integer();
                    $v->addColumn('page', '当前页码')
                        ->integer();
                    if (isset($params['recommend_status'])) {
                        $v->addColumn('recommend_status', '推荐状态')->integer();
                    }
                    if (isset($params['act_status'])) {
                        $v->addColumn('act_status', '活动状态')->integer();
                    }
                    break;
                }
            case 'getRobotAnswer':
                {
                    $v->addColumn('topic_id', '题目id')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('score', '积分')
                        ->integer();
                    break;
                }
            case 'saveActivity':
                {
                    $v->addColumn('title', '竞赛标题')
                        ->required('不能为空')
                        ->notEmpty();
                    $v->addColumn('type', '展示模式')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('description', '竞赛描述')
                        ->required('不能为空')
                        ->notEmpty();
                    $v->addColumn('start_time', '开始时间')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('end_time', '结束时间')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('paper_status', '试卷状态')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('act_status', '活动状态')
                        ->required('不能为空')
                        ->integer();
                    if (isset($params['act_id'])) {
                        $v->addColumn('act_id', '竞赛id')->integer();
                    }
                    if (isset($params['recommend_status'])) {
                        $v->addColumn('recommend_status', '推荐状态')->integer();
                    }
                    if (isset($params['recommend_index'])) {
                        $v->addColumn('recommend_index', '推荐序号')->integer();
                    }
                    break;
                }
            case 'delActivity':
                {
                    $v->addColumn('act_id', '竞赛id')
                        ->required('不能为空')
                        ->integer()
                        ->min(0);
                    break;
                }
            case 'getActivity':
                {
                    $v->addColumn('act_id', '竞赛id')
                        ->required('不能为空')
                        ->integer();
                    break;
                }
            case 'getActivityList':
                {
                    $v->addColumn('recommend_status', '推荐状态')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('limit', '列表数')
                        ->required('不能为空')
                        ->integer();
                    break;
                }
            case 'getPaper':
                {
                    $v->addColumn('act_id', '竞赛id')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('paper_nums', '试卷题量')
                        ->required('不能为空')
                        ->integer();
                    break;
                }
            case 'addPaperTopic':
                {
                    $v->addColumn('act_id', '竞赛id')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('topic_id', '题目id')
                        ->required('不能为空')
                        ->notEmpty();
                    $v->addColumn('topic_title', '题目标题')
                        ->required('不能为空')
                        ->notEmpty();
                    $v->addColumn('topic_label', '题目标签')
                        ->required('不能为空')
                        ->notEmpty();
                    break;
                }
            case 'delPaperTopic':
                {
                    $v->addColumn('act_id', '竞赛id')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('topic_id', '题目id')
                        ->required('不能为空')
                        ->notEmpty();
                    break;
                }
            case 'updatePaper':
                {
                    $v->addColumn('act_id', '竞赛id')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('type', '答题类型')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('nums', '题量')
                        ->required('不能为空')
                        ->integer();
                    break;
                }
            case 'updateScoreSet':
                {
                    $v->addColumn('per_score', '答对得分')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('win_score', '获胜得分')
                        ->required('不能为空')
                        ->integer();
                    $v->addColumn('fail_score', '失败得分')
                        ->required('不能为空')
                        ->integer();
                    break;
                }
        }
        return $v;
    }


App/HttpController/BaseController.php
这是老式编程语bai言里的标签跳转, 相当于C语言du里面的goto语句
可以实现 分支选择zhi, 循环等功能
sed '/^AA/ba;s/$/ NO/;b;:a;s/$/ YES/' 解读如下dao
sed是逐行扫描的
/^AA/ba;s/$/ NO/ 意思是如果当前行句首是AA
则跳转到标签a,执行s/$/ YES/ 即在行末插入YES (这里使用替换s命令实现插入)
否则执行s/$/ NO/, 在行末插入NO
对所有行都执行这种操作, 大功告成




echo 1 2 3 4 5 6 7 8 9 10 | perl -p -e 's#(\d+) #\1\n#g' | sort -n -k 1 | sed -e :a -e '$d;N;2,3ba' -e 'P;D'

3ba表示去掉最后3行,你要保留最新的5个,那就是5ba好了


sed -n '/^Handle/{:a;N;/\n$/!{$!ba};s/.*Range Size: \([^\n]*\).*/\1/p}' file
[解析]
文本就3个段落,2个空行为分割,用sed首先想到肯定是以空行为分割,把一整段文本读取在一起,然后统一进行匹配和替换,特别注意N读取内容匹配空行是 /\n$/ ,而不是一般的 /^$/  ,另一个问题是到了尾行因为没有下面的空行来激活,所以我们要在前面加个尾行的匹配跳转。这样就可以成功替换以Handle开头的段落内容,如果没匹配到也当然不会打印。


sed -n 'H;/^$/!{$!b};x;s/\nHandle.*Range Size: \([^\n]*\).*/\1/p' file
[解析]
因为是以空行为分割,H 追加到 hold space ,后面的替换只对空行或者最后一行才执行,否则都会跳过,也只有符合关键字的才会被替换打印。其他的行则因为 -n 的原因不会被输出。


From:https://blog.csdn.net/woshizhangliang999/article/details/53379158
从Macbook通过iTerm2的SSH连接到其它linux实现iTerm2远程pbcopy,前几周我也想过,但是不知怎么实现,
前两天鸟哥在其微信朋友圈里贴了一个PHP版本的实现思路,我这实践了一下,用Go语言实现了使用起来顺手,

于是在想,可能很多人都有这个需求,于是写下我的实现过程,拿走不谢,PHP是最好的语言没有之一,如下:


使用OSC52实现iTerm2远程pbcopy实现模仿Mac的pbcopy的拷贝最基础原理如下:


关于PHP实现的鸟哥版本pbcopy的详细情况见如下链接:
https://mp.weixin.qq.com/s/-aFTI32LWCJG_7aEuCUBgw


现在,开启swoole顾问的GO实现正文:
上面是摘录来自鸟哥的文章,他是用PHP实现了的,但是PHP不是每台机器都有且没有PHP怎么办呢?
于是用Go歪歪斜斜的写了一个,以力求实现功能就算是很OK了,实践发现果然OK的,有鸟哥加持嘛!

pbcopy.go


在MacBook上面编译成Linux上可运行的pbcopy,如不这样会报-bash: ./pbcopy: 无法执行二进制文件错:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o pbcopy pbcopy.go


从MAC机上编译成功后把上面的二进制GO文件扔到CentOS的服务器上,修改iTerm2连接远程机器设置,

点击在新窗口中浏览此图片

运行,就成功复制到Mac的剪切板上了,注意一定是用iTerm2软件下ssh连接远程服务器,不是在secureCRT:
echo "osc520 codes" | /home/xiangdong/bin/pbcopy


最后,就是把/home/xiangdong/bin/pbcopy 加到那个Linux 的环境PATH变量里了,如下:
chmod +x ~/bin/pbcopy

vim  ~/.bashrc      #/home/xiangdong/.bashrc 把这个pbcopy路径加到PATH环境变量里面去,下次不用再输入绝对路径了。
export PATH=/home/xiangdong/bin:$PATH


$tree  ~+/bin/
/home/xiangdong/bin/
├── kubeladder
└── pbcopy


就可直接运行pbcopy了,不用加点了:
echo "osc520 codes" |pbcopy

最后,
鸟哥微信朋友圈问了一喙,这个能否在secureCRT里也支持一下呢,可不就可以批量部署到控制机上,拷贝操作更完美了。

目前在secreCRT里运行输出如下:
$echo "osc540 codes" |pbcopy
;;b3NjNTQwIGNvZGVz


乔大妈给了一个纯shell的白膘(月票)版本:
cat  ~/.bashrc
alias pbcopy2="(printf '\033]1337;CopyToClipboard=\7'; cat -; printf '\033]1337;EndCopy\7')"

echo "osc520 codes" |pbcopy2
osc520 codes
osc52000 codes
Shell 也可以包含外部脚本, 可以封装一些公共的代码为单独文件,需要用的时候直接引用。
方法有两种, 分别是.和source, 如下:
1)我看在centos6.X里面的/etc/init.d/nginx就是用的点空格引入的。



2)无论是source还是点空格最好是用绝对路径:
放在同一个目录下,所以source ./import.sh 引用看起来没有问题, 但是如果在上一层目录运行脚本时会出错,如下:
$ sh shell_testing/test.sh
shell_testing/test.sh: line 4: ./import.sh: No such file or directory
实践如下,相当于shell去包含./import.sh是从运行目录去包含的,去了上层目录就认为./import.sh是在上一层目录下面,所以得用绝对路径:


所以引用的话最好使用绝对路径, 其实也就是test.sh脚本的绝对路径,因为这两个脚本放在同一个目录下。
import.sh


test.sh


$./test.sh
LiLei
EOF
Your name is LiLei

注意:
1.两个点之间,有空格,千万注意.
2.两个脚本不在同一目录,要用绝对路径
3.为简单起见,通常用第一种方法

摘自链接:https://www.jianshu.com/p/cc4dda1fb77f


在两个机房里这两个VIP下面有很多的服务,如果用ansible一次性给干死了,但是这个java的进程要启动得15秒,也就出现了集体同时在启动中,没有对外服务,怎么办?只有先后启动,这时就有用了,两个机房的一些机器15秒后启动,一些机器立即启动,错开启动的好处是,两个机房能同时对外提供服务:
/data/www/ai.xxx.xxxx.com/server/start.sh



/data/www/ai.xxx.xxxx.com/server/stop.sh


延后启动的shell文件引用:
/data/www/ai.xxx.xxxx.com/bin/delayRestart.sh


直接启动的shell文件无 sleep 15:



还是相对路径问题,得修改这个jar包路径为绝对路径:
/data/www/ai.xxx.xxxx.com/bin/output.log
Error: Unable to access jarfile eladmin-system-3.1.jar


实践成功部署如下:
ansible ai_web -a'ps -eo pid,lstart,etime,cmd | grep eladmin-system|grep -v grep'  
10.73.234.136 | CHANGED | rc=0 >>  
24238 Thu May 21 14:21:03 2020       02:28 java -jar -Xms1024m -Xmx4096m -XX:MetaspaceSize=1024M -XX:MaxMetaspaceSize=4096m /data/www/ai.xxx.xxxx.com/server/eladmin-system-3.1.jar --spring.profiles.active=prod  
10.73.234.137 | CHANGED | rc=0 >>  
34282 Thu May 21 14:21:19 2020       02:12 java -jar -Xms1024m -Xmx4096m -XX:MetaspaceSize=1024M -XX:MaxMetaspaceSize=4096m /data/www/ai.xxx.xxxx.com/server/eladmin-system-3.1.jar --spring.profiles.active=prod  
10.169.70.72 | CHANGED | rc=0 >>  
52665 Thu May 21 14:21:19 2020       02:12 java -jar -Xms1024m -Xmx4096m -XX:MetaspaceSize=1024M -XX:MaxMetaspaceSize=4096m /data/www/ai.xxx.xxxx.com/server/eladmin-system-3.1.jar --spring.profiles.active=prod  
10.169.70.71 | CHANGED | rc=0 >>  
31033 Thu May 21 14:21:04 2020       02:27 java -jar -Xms1024m -Xmx4096m -XX:MetaspaceSize=1024M -XX:MaxMetaspaceSize=4096m /data/www/ai.xxx.xxxx.com/server/eladmin-system-3.1.jar --spring.profiles.active=prod  
分页: 1/26 第一页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 下页 最后页 [ 显示模式: 摘要 | 列表 ]