java处理csv分割时双引号中的逗号

最近用java写一个小工具处理csv,不想引用额外的库,一开始使用split(“,”)分割,发现当双引号文本中有逗号时会分割错误,上网查一下,可以用正则表达式进行分割,避免分割错误。

正则表达式:

// 双引号文本正则,未转义
,(?=(?:[^"]*"[^"]*")*[^"]*$)
// 单引号文本正则,未转义
,(?=(?:[^']*'[^']*')*[^']*$)
regex

代码:

String line = "foo,bar,c;qual=\"baz,blurb\",d;junk=\"quux,syzygy\"";
String[] tokens = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
Java

bash脚本列出文件供选择

前一阵子写bash脚本实现选择备份文件恢复,记录一下实现方法

实现脚本:

restore(){
    # 备份文件夹
    BACKUP_PATH=/backup
    n=0
    # 从备份文件夹读取10条最新的记录
    for bak in `ls -t $BACKUP_PATH|sed -n '1,10p'`
    do
     n=$((n+1))
     printf "[%s] %s\n" "$n" "$bak"
     eval "bak${n}=$bak"
    done

    if [ "$n" -eq 0 ]
    then
    echo >&2 "未找到备份文件"
    exit
    fi

    printf "选择需要恢复的备份文件ID(1 to %s):" "$n"
    read -r num
    num=$(printf "%s\n" "$num" |tr -dc '[:digit:]')
    if [ "$num" -le 0 ] || [ "$num" -gt "$n" ]
    then
    echo >&2 "输入有误"
    exit 1
    else
    eval "bak=\$bak${num}"
    fi

    RESTORE_PATH=$BACKUP_PATH/$bak
    #下面进行恢复操作
}
Bash

使用podman运行程序及通过systemd管理

运行容器

podman run -d --name nginx -p 8080:80 docker.io/nginx:latest
Bash

生成systemd配置文件

podman generate systemd --new --files nginx
# 输出
# /root/container-90346186cab3adcaf462790c6bf1cdeed045c6129fa28dbed6f9dc9579ccb1da.service
Bash

复制systemd配置

mv container-90346186cab3adcaf462790c6bf1cdeed045c6129fa28dbed6f9dc9579ccb1da.service ~/.config/systemd/user/container-nginx.service
Bash

重载systemd服务

systemctl --user daemon-reload
Bash

启动服务及开机启动

systemctl --user enable sing-box
systemctl --user start sing-box
Bash

podman自动更新

启动时添加label

podman run -d --name nginx -p 8080:80 --label "io.containers.autoupdate=registry" docker.io/nginx:latest
Bash

添加systemd服务后执行podman auto-update即可自动更新到最新镜像

podman auto-update
Bash

使用pyinstaller打包python程序

使用pip安装

pip install pyinstaller
PowerShell

使用pyinstaller打包

pyinstaller [options] myscript.py
PowerShell

常用选项参数

-D,–onedir输出到一个文件夹
-F,–onefile输出到一个文件
–add-data <SRC;DEST or SRC:DEST>打包资源文件
-c, –console, –nowindowed运行时打开控制台窗口
-w, –windowed, –noconsole运行时不打开控制台窗口

python虚拟环境管理venv使用

最近用python写一个工具给别人用,用pyinstaller打包,发现会把所有依赖都打包进去,导致打包结果很大,网上搜了一下可以使用python3.6以上自带虚拟环境管理venv创建虚拟环境再安装必要依赖。

官方文档:venv — 创建虚拟环境 — Python 3.11.4 文档

创建虚拟环境

<span role="button" tabindex="0" data-code="python -m venv
python -m venv <虚拟环境目录>
PowerShell

激活虚拟环境

<span role="button" tabindex="0" data-code="#windows cmd <虚拟环境目录>\Scripts\activate.cmd powershell <虚拟环境目录>\Scripts\Activate.ps1 source
#windows cmd
<虚拟环境目录>\Scripts\activate.cmd
#windows powershell
<虚拟环境目录>\Scripts\Activate.ps1
#linux
source <虚拟环境目录>/Scripts/activate
PowerShell

退出虚拟环境

deactivate
PowerShell

vue自定义指令实现禁止复制功能

原理

设置元素oncontextmenu与onselectstart事件直接返回

注册自定义指令blockcopy

import Vue form 'vue'

Vue.directive('watermark', {
  bind: function (el) {
    el.oncontextmenu = () => {
      return false;
    };
    el.onselectstart = () => {
      return false;
    };
  }
}
JavaScript

引入blockcopy.js文件

import 'blockcopy.js'
JavaScript

使用blockcopy指令

<span role="button" tabindex="0" data-code="<template> <div v-blockcopy ></div>
<template>
    <div v-blockcopy ></div>
</template>
Vue HTML

vue自定义指令实现水印

原理

使用自定义vue指令,使用canvas生成水印图片,设置元素背景使水印生效。

注册watermark指令

<span role="button" tabindex="0" data-code="import Vue from 'vue' Vue.directive('watermark', { bind: function (el, binding) { const addWaterMarker = (settings, el) => { const defaultSettings = { type: 1,//1-创建div子元素,2-设置元素背景图 text: '默认水印', textArray: [], width: 200, height: 140, fontSize: 18, fontFamily: 'Microsoft Yahei', fontColor: 'rgba(0,0,0,0.1)', textAlign: 'left', textBaseline: 'Middle', fillTextX: 10 }; settings = Object.assign(defaultSettings, settings); // 检查父元素是否包含子元素 const elementContains = (parent, child) => parent !== child && parent.contains(child); const flag = elementContains(el, document.querySelector('canvas')); // 防止重复创建 if (!flag) { let canvas = document.createElement('canvas'); canvas.width = settings.width; canvas.height = settings.height; canvas.style.display = 'none'; el.appendChild(canvas); let cans = can.getContext('2d'); cans.rotate(-20 * Math.PI / 180); cans.font = `${settings.fontSize}px ${settings.fontFamily}`; cans.fillStyle = settings.fontColor; cans.textAlign = settings.textAlign; cans.textBaseline = settings.textBaseline; if (settings.textArray && settings.textArray.length > 0) { //多行水印 for (let i = 0; i
import Vue from 'vue'

Vue.directive('watermark', {
  bind: function (el, binding) {
    const addWaterMarker = (settings, el) => {
      const defaultSettings = {
        type: 1,//1-创建div子元素,2-设置元素背景图
        text: '默认水印',
        textArray: [],
        width: 200,
        height: 140,
        fontSize: 18,
        fontFamily: 'Microsoft Yahei',
        fontColor: 'rgba(0,0,0,0.1)',
        textAlign: 'left',
        textBaseline: 'Middle',
        fillTextX: 10
      };
      settings = Object.assign(defaultSettings, settings);
      // 检查父元素是否包含子元素
      const elementContains = (parent, child) => parent !== child && parent.contains(child);
      const flag = elementContains(el, document.querySelector('canvas'));
      // 防止重复创建
      if (!flag) {
        let canvas = document.createElement('canvas');
        canvas.width = settings.width;
        canvas.height = settings.height;
        canvas.style.display = 'none';
        el.appendChild(canvas);

        let cans = can.getContext('2d');
        cans.rotate(-20 * Math.PI / 180);
        cans.font = `${settings.fontSize}px ${settings.fontFamily}`;
        cans.fillStyle = settings.fontColor;
        cans.textAlign = settings.textAlign;
        cans.textBaseline = settings.textBaseline;

        if (settings.textArray && settings.textArray.length > 0) {
          //多行水印
          for (let i = 0; i < settings.textArray.length; i++) {
            cans.fillText(
              settings.textArray[i],
              settings.fillTextX,
              settings.height / 2 + i * settings.fontSize * 2
            )
          }
        }
        else if (settings.text && settings.text.length > 0) {
          //单行水印
          cans.fillText(settings.text, settings.fillTextX, canvas.height)
        }
        else {
            return;
        }

        if (settings.type === 1) {
          // 创建div 定位覆盖(某个元素,如图片添加水印建议使用此方法)
          let div = document.createElement('div');
          div.id = str;
          div.style.pointerEvents = 'none';
          div.style.top = '0';
          div.style.left = '0';
          div.style.position = 'absolute';
          div.style.zIndex = '100000';
          div.style.width = '100%';
          div.style.height = '100%';
          div.style.background = 'url(' + can.toDataURL('image/png') + ')';
          el.appendChild(div);
        }
        else if (settings.type === 2) {
          // 设置背景图(整个项目中都添加水印建议使用此方法)
          el.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
        }
      }
    }
    addWaterMarker(binding.value, el)
  }
})
JavaScript

引入watermark文件

import 'watermark.js"
JavaScript

调用指令

<span role="button" tabindex="0" data-code="<template> <div v-watermark="{text: '水印名称', textColor: 'rgba(180, 180, 180, 0.3)'}" > </div>
<template>
  <div v-watermark="{text: '水印名称', textColor: 'rgba(180, 180, 180, 0.3)'}" >
    
  </div>
</template>
Vue HTML

使用Axios发送post请求下载文件

原理

  1. 设置axios的responseType为blob
  2. 前端使用Blob接收数据,创建a标签进行保存文件

代码实现

axios.post(url, {...someData}, {responseType: 'blob'})
    .then((res) => {
        const { data, headers } = res
        const fileName = headers['content-disposition'].replace(/\w+;(?:filename\*=utf-8'(?:\w+)?'|filename=)(.*)/, '$1')
        const blob = new Blob([data], {type: headers['content-type']})
        let dom = document.createElement('a')
        let url = window.URL.createObjectURL(blob)
        dom.href = url
        dom.download = decodeURI(fileName)
        dom.style.display = 'none'
        document.body.appendChild(dom)
        dom.click()
        dom.parentNode.removeChild(dom)
        window.URL.revokeObjectURL(url)
    }).catch((err) => {})
JavaScript

rhel8使用realmd入ad域使用域用户验证

设置dns能够解析ad域域名

安装相关包

yum -y install  sssd oddjob oddjob-mkhomedir adcli samba-common-tools
Bash

使用realm命令加入ad域

realm join example.com
Password for administrator: #这里输入域管理员密码
Bash

查看是否加入成功

realm list
example.com
  type: kerberos
  realm-name: EXAMPLE.COM
  domain-name: example.com
  configured: kerberos-member
  server-software: active-directory
  client-software: sssd
  required-package: oddjob
  required-package: oddjob-mkhomedir
  required-package: sssd
  required-package: adcli
  required-package: samba-common-tools
  login-formats: %[email protected]
  login-policy: allow-realm-logins
Bash

修改/etc/sssd/sssd.conf配置文件

use_fully_qualified_names = False  #设置为False可以不带域名登录
fallback_homedir = /home/%d/%u     #可选,修改域用户的home目录路径
Bash

重启服务器

验证域用户

禁止所有域用户登录

realm deny --all
Bash

允许某个组或某个用户登录

realm permit -g 'xx用户组'
realm permit [email protected]
Bash

配置sudo权限

%xxx用户组@example.com ALL=(ALL) ALL
[email protected] ALL=(ALL) ALL
Bash

使用cwRsync客户端同步

从https://www.itefix.net/cwrsync-client下载cwRsync

生成ssh key并添加到服务器

解压cwRsync压缩包,bin文件夹中的rsync.exe就是执行文件

访问本地目录,例如c盘,通过添加前缀访问/cygdrive/c/

使用ssh key免密访问,通过-e “ssh -i key”参数设置

例子:

C:\cwrsync_6.2.8_x64_free\bin\rsync.exe -avP -e "/cygdrive/c/cwrsync_6.2.8_x64_free/bin/ssh -i /cygdrive/c/Users/Administrator/.ssh/id_ed25519" /cygdrive/d/localdir/ test@remote:/remotedir/
cmd

VS2022添加.Net4.0/4.5支持

VS2022默认不再支持.Net4.0/4.5框架的项目

  1. nuget搜索Microsoft.NETFramework.ReferenceAssemblies,找到所需的版本。
  2. 比如“Microsoft.NETFramework.ReferenceAssemblies.net40”。
  3. 进入详情页点击“Download package”按钮进行下载保存。
  4. 得到“microsoft.netframework.referenceassemblies.net40.1.0.3.nupkg”文件,使用压缩工具进行解压。
  5. 目录中的“build\.NETFramework\v4.0”文件夹复制到“C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0”。
  6. 重启VS2022,就可以实现对旧版本的支持。
  7. 下载对应的版本执行相同的操作即可安装。

Windows下通过PowerShell修改文件创建时间

windows下文件有创建时间、修改时间、访问时间3个属性,可以通过powershell修改这三个属性。

主要通过修改以下3个属性实现

# 创建时间
$(Get-Item FILENAME.EXT).CreationTime=$(DATE)
# 修改时间
$(Get-Item FILENAME.EXT).LastWriteTime=$(DATE)
# 访问时间
$(Get-Item FILENAME.EXT).LastAccessTime=$(DATE)
PowerShell

批量修改文件夹中的文件

$modifyfiles = Get-ChildItem -force | Where-Object { ! $_.PSIsContainer }
foreach ($object in $modifyfiles) {
    $object.CreationTime = ("11/11/2011 12:00:00")
    $object.LastAccessTime = ("11/11/2011 12:00:00")
    $object.LastWritetime = ("11/11/2011 12:00:00")
}
PowerShell

修改单个文件、文件夹

Get-Item  C:\testFolder1 | % {$_.CreationTime = '01/11/2004 22:13:36'}
Get-Item  C:\testFile1.txt | % {$_.CreationTime = '01/11/2005 06:00:36'}
PowerShell